Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: openvswitch: add explicit drop action

From: Eric Garver <eric@garver.life>

This adds an explicit drop action. This is used by OVS to drop packets
for which it cannot determine what to do. An explicit action in the
kernel allows passing the reason _why_ the packet is being dropped or
zero to indicate no particular error happened (i.e: OVS intentionally
dropped the packet).

Since the error codes coming from userspace mean nothing for the kernel,
we squash all of them into only two drop reasons:
- OVS_DROP_EXPLICIT_WITH_ERROR to indicate a non-zero value was passed
- OVS_DROP_EXPLICIT to indicate a zero value was passed (no error)

e.g. trace all OVS dropped skbs

# perf trace -e skb:kfree_skb --filter="reason >= 0x30000"
[..]
106.023 ping/2465 skb:kfree_skb(skbaddr: 0xffffa0e8765f2000, \
location:0xffffffffc0d9b462, protocol: 2048, reason: 196611)

reason: 196611 --> 0x30003 (OVS_DROP_EXPLICIT)

Also, this patch allows ovs-dpctl.py to add explicit drop actions as:
"drop" -> implicit empty-action drop
"drop(0)" -> explicit non-error action drop
"drop(42)" -> explicit error action drop

Signed-off-by: Eric Garver <eric@garver.life>
Co-developed-by: Adrian Moreno <amorenoz@redhat.com>
Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Garver and committed by
David S. Miller
e7bc7db9 ec7bfb5e

+40 -5
+2
include/uapi/linux/openvswitch.h
··· 965 965 * start of the packet or at the start of the l3 header depending on the value 966 966 * of l3 tunnel flag in the tun_flags field of OVS_ACTION_ATTR_ADD_MPLS 967 967 * argument. 968 + * @OVS_ACTION_ATTR_DROP: Explicit drop action. 968 969 * 969 970 * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all 970 971 * fields within a header are modifiable, e.g. the IPv4 protocol and fragment ··· 1003 1002 OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */ 1004 1003 OVS_ACTION_ATTR_ADD_MPLS, /* struct ovs_action_add_mpls. */ 1005 1004 OVS_ACTION_ATTR_DEC_TTL, /* Nested OVS_DEC_TTL_ATTR_*. */ 1005 + OVS_ACTION_ATTR_DROP, /* u32 error code. */ 1006 1006 1007 1007 __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted 1008 1008 * from userspace. */
+9
net/openvswitch/actions.c
··· 1485 1485 return dec_ttl_exception_handler(dp, skb, 1486 1486 key, a); 1487 1487 break; 1488 + 1489 + case OVS_ACTION_ATTR_DROP: { 1490 + enum ovs_drop_reason reason = nla_get_u32(a) 1491 + ? OVS_DROP_EXPLICIT_WITH_ERROR 1492 + : OVS_DROP_EXPLICIT; 1493 + 1494 + ovs_kfree_skb_reason(skb, reason); 1495 + return 0; 1496 + } 1488 1497 } 1489 1498 1490 1499 if (unlikely(err)) {
+2
net/openvswitch/drop.h
··· 11 11 #define OVS_DROP_REASONS(R) \ 12 12 R(OVS_DROP_LAST_ACTION) \ 13 13 R(OVS_DROP_ACTION_ERROR) \ 14 + R(OVS_DROP_EXPLICIT) \ 15 + R(OVS_DROP_EXPLICIT_WITH_ERROR) \ 14 16 /* deliberate comment for trailing \ */ 15 17 16 18 enum ovs_drop_reason {
+9 -1
net/openvswitch/flow_netlink.c
··· 38 38 #include <net/tun_proto.h> 39 39 #include <net/erspan.h> 40 40 41 + #include "drop.h" 41 42 #include "flow_netlink.h" 42 43 43 44 struct ovs_len_tbl { ··· 62 61 case OVS_ACTION_ATTR_RECIRC: 63 62 case OVS_ACTION_ATTR_TRUNC: 64 63 case OVS_ACTION_ATTR_USERSPACE: 64 + case OVS_ACTION_ATTR_DROP: 65 65 break; 66 66 67 67 case OVS_ACTION_ATTR_CT: ··· 2396 2394 /* Whenever new actions are added, the need to update this 2397 2395 * function should be considered. 2398 2396 */ 2399 - BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23); 2397 + BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 24); 2400 2398 2401 2399 if (!actions) 2402 2400 return; ··· 3184 3182 [OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1, 3185 3183 [OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls), 3186 3184 [OVS_ACTION_ATTR_DEC_TTL] = (u32)-1, 3185 + [OVS_ACTION_ATTR_DROP] = sizeof(u32), 3187 3186 }; 3188 3187 const struct ovs_action_push_vlan *vlan; 3189 3188 int type = nla_type(a); ··· 3454 3451 if (err) 3455 3452 return err; 3456 3453 skip_copy = true; 3454 + break; 3455 + 3456 + case OVS_ACTION_ATTR_DROP: 3457 + if (!nla_is_last(a, rem)) 3458 + return -EINVAL; 3457 3459 break; 3458 3460 3459 3461 default:
+18 -4
tools/testing/selftests/net/openvswitch/ovs-dpctl.py
··· 301 301 ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"), 302 302 ("OVS_ACTION_ATTR_ADD_MPLS", "none"), 303 303 ("OVS_ACTION_ATTR_DEC_TTL", "none"), 304 + ("OVS_ACTION_ATTR_DROP", "uint32"), 304 305 ) 305 306 306 307 class ctact(nla): ··· 448 447 print_str += "recirc(0x%x)" % int(self.get_attr(field[0])) 449 448 elif field[0] == "OVS_ACTION_ATTR_TRUNC": 450 449 print_str += "trunc(%d)" % int(self.get_attr(field[0])) 450 + elif field[0] == "OVS_ACTION_ATTR_DROP": 451 + print_str += "drop(%d)" % int(self.get_attr(field[0])) 451 452 elif field[1] == "flag": 452 453 if field[0] == "OVS_ACTION_ATTR_CT_CLEAR": 453 454 print_str += "ct_clear" ··· 471 468 while len(actstr) != 0: 472 469 parsed = False 473 470 if actstr.startswith("drop"): 474 - # for now, drops have no explicit action, so we 475 - # don't need to set any attributes. The final 476 - # act of the processing chain will just drop the packet 477 - return 471 + # If no reason is provided, the implicit drop is used (i.e no 472 + # action). If some reason is given, an explicit action is used. 473 + actstr, reason = parse_extract_field( 474 + actstr, 475 + "drop(", 476 + "([0-9]+)", 477 + lambda x: int(x, 0), 478 + False, 479 + None, 480 + ) 481 + if reason is not None: 482 + self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason]) 483 + parsed = True 484 + else: 485 + return 478 486 479 487 elif parse_starts_block(actstr, "^(\d+)", False, True): 480 488 actstr, output = parse_extract_field(