Skip to content

Commit a6ac667

Browse files
committed
Merge branch 'net-bridge-add-skb-drop-reasons-to-the-most-common-drop-points'
Radu Rendec says: ==================== net/bridge: Add skb drop reasons to the most common drop points The bridge input code may drop frames for various reasons and at various points in the ingress handling logic. Currently kfree_skb() is used everywhere, and therefore no drop reason is specified. Add drop reasons to the most common drop points. The purpose of this series is to address the most common drop points on the bridge ingress path. It does not exhaustively add drop reasons to the entire bridge code. The intention here is to incrementally add drop reasons to the rest of the bridge code in follow up patches. Most of the skb drop points that are addressed in this series can be easily tested by sending crafted packets. The diagram below shows a simple test configuration, and some examples using `packit`(*) are also included. The bridge is set up with STP disabled. (*) https://github.com/resurrecting-open-source-projects/packit The following changes were *not* tested: * SKB_DROP_REASON_NOMEM in br_flood(). It's not easy to trigger an OOM condition for testing purposes, while everything else works correctly. * All drop reasons in br_multicast_flood(). I could not find an easy way to make a crafted packet get there. * SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE in br_handle_frame_finish() when the port state is BR_STATE_DISABLED, because in that case the frame is already dropped in the switch/case block at the end of br_handle_frame(). +-------+ | br0 | +---+---+ | +---+---+ veth pair +-------+ | veth0 +-------------+ xeth0 | +-------+ +-------+ SKB_DROP_REASON_MAC_INVALID_SOURCE - br_handle_frame() packit -t UDP -s 192.168.0.1 -d 192.168.0.2 -S 8000 -D 8000 \ -e 01:22:33:44:55:66 -E aa:bb:cc:dd:ee:ff -c 1 \ -p '0x de ad be ef' -i xeth0 SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL - br_handle_frame() packit -t UDP -s 192.168.0.1 -d 192.168.0.2 -S 8000 -D 8000 \ -e 02:22:33:44:55:66 -E 01:80:c2:00:00:01 -c 1 \ -p '0x de ad be ef' -i xeth0 SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE - br_handle_frame() bridge link set dev veth0 state 0 # disabled packit -t UDP -s 192.168.0.1 -d 192.168.0.2 -S 8000 -D 8000 \ -e 02:22:33:44:55:66 -E aa:bb:cc:dd:ee:ff -c 1 \ -p '0x de ad be ef' -i xeth0 SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE - br_handle_frame_finish() bridge link set dev veth0 state 2 # learning packit -t UDP -s 192.168.0.1 -d 192.168.0.2 -S 8000 -D 8000 \ -e 02:22:33:44:55:66 -E aa:bb:cc:dd:ee:ff -c 1 \ -p '0x de ad be ef' -i xeth0 SKB_DROP_REASON_NO_TX_TARGET - br_flood() packit -t UDP -s 192.168.0.1 -d 192.168.0.2 -S 8000 -D 8000 \ -e 02:22:33:44:55:66 -E aa:bb:cc:dd:ee:ff -c 1 \ -p '0x de ad be ef' -i xeth0 ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 6ad7f71 + 623e43c commit a6ac667

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

drivers/net/vxlan/vxlan_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,7 +2798,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
27982798
dev_dstats_tx_dropped(dev);
27992799
vxlan_vnifilter_count(vxlan, vni, NULL,
28002800
VXLAN_VNI_STATS_TX_DROPS, 0);
2801-
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
2801+
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
28022802
return NETDEV_TX_OK;
28032803
}
28042804
}
@@ -2821,7 +2821,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
28212821
if (fdst)
28222822
vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
28232823
else
2824-
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
2824+
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
28252825
}
28262826

28272827
return NETDEV_TX_OK;

drivers/net/vxlan/vxlan_mdb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,7 @@ netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
17121712
vxlan_xmit_one(skb, vxlan->dev, src_vni,
17131713
rcu_dereference(fremote->rd), false);
17141714
else
1715-
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
1715+
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
17161716

17171717
return NETDEV_TX_OK;
17181718
}

include/net/dropreason-core.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,13 @@
106106
FN(VXLAN_VNI_NOT_FOUND) \
107107
FN(MAC_INVALID_SOURCE) \
108108
FN(VXLAN_ENTRY_EXISTS) \
109-
FN(VXLAN_NO_REMOTE) \
109+
FN(NO_TX_TARGET) \
110110
FN(IP_TUNNEL_ECN) \
111111
FN(TUNNEL_TXINFO) \
112112
FN(LOCAL_MAC) \
113113
FN(ARP_PVLAN_DISABLE) \
114+
FN(MAC_IEEE_MAC_CONTROL) \
115+
FN(BRIDGE_INGRESS_STP_STATE) \
114116
FNe(MAX)
115117

116118
/**
@@ -497,8 +499,8 @@ enum skb_drop_reason {
497499
* entry or an entry pointing to a nexthop.
498500
*/
499501
SKB_DROP_REASON_VXLAN_ENTRY_EXISTS,
500-
/** @SKB_DROP_REASON_VXLAN_NO_REMOTE: no remote found for xmit */
501-
SKB_DROP_REASON_VXLAN_NO_REMOTE,
502+
/** @SKB_DROP_REASON_NO_TX_TARGET: no target found for xmit */
503+
SKB_DROP_REASON_NO_TX_TARGET,
502504
/**
503505
* @SKB_DROP_REASON_IP_TUNNEL_ECN: skb is dropped according to
504506
* RFC 6040 4.2, see __INET_ECN_decapsulate() for detail.
@@ -520,6 +522,16 @@ enum skb_drop_reason {
520522
* enabled.
521523
*/
522524
SKB_DROP_REASON_ARP_PVLAN_DISABLE,
525+
/**
526+
* @SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL: the destination MAC address
527+
* is an IEEE MAC Control address.
528+
*/
529+
SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL,
530+
/**
531+
* @SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE: the STP state of the
532+
* ingress bridge port does not allow frames to be forwarded.
533+
*/
534+
SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE,
523535
/**
524536
* @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
525537
* shouldn't be used as a real 'reason' - only for tracing code gen

net/bridge/br_forward.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
201201
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
202202
u16 vid)
203203
{
204+
enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
204205
struct net_bridge_port *prev = NULL;
205206
struct net_bridge_port *p;
206207

@@ -234,8 +235,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
234235
continue;
235236

236237
prev = maybe_deliver(prev, p, skb, local_orig);
237-
if (IS_ERR(prev))
238+
if (IS_ERR(prev)) {
239+
reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
240+
SKB_DROP_REASON_NOT_SPECIFIED;
238241
goto out;
242+
}
239243
}
240244

241245
if (!prev)
@@ -249,7 +253,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
249253

250254
out:
251255
if (!local_rcv)
252-
kfree_skb(skb);
256+
kfree_skb_reason(skb, reason);
253257
}
254258

255259
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
@@ -289,6 +293,7 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
289293
struct net_bridge_mcast *brmctx,
290294
bool local_rcv, bool local_orig)
291295
{
296+
enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
292297
struct net_bridge_port *prev = NULL;
293298
struct net_bridge_port_group *p;
294299
bool allow_mode_include = true;
@@ -329,8 +334,11 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
329334
}
330335

331336
prev = maybe_deliver(prev, port, skb, local_orig);
332-
if (IS_ERR(prev))
337+
if (IS_ERR(prev)) {
338+
reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
339+
SKB_DROP_REASON_NOT_SPECIFIED;
333340
goto out;
341+
}
334342
delivered:
335343
if ((unsigned long)lport >= (unsigned long)port)
336344
p = rcu_dereference(p->next);
@@ -349,6 +357,6 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
349357

350358
out:
351359
if (!local_rcv)
352-
kfree_skb(skb);
360+
kfree_skb_reason(skb, reason);
353361
}
354362
#endif

net/bridge/br_input.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
7575
/* note: already called with rcu_read_lock */
7676
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
7777
{
78+
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
7879
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
7980
enum br_pkt_type pkt_type = BR_PKT_UNICAST;
8081
struct net_bridge_fdb_entry *dst = NULL;
@@ -96,8 +97,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
9697
if (br_mst_is_enabled(br)) {
9798
state = BR_STATE_FORWARDING;
9899
} else {
99-
if (p->state == BR_STATE_DISABLED)
100+
if (p->state == BR_STATE_DISABLED) {
101+
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
100102
goto drop;
103+
}
101104

102105
state = p->state;
103106
}
@@ -155,8 +158,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
155158
}
156159
}
157160

158-
if (state == BR_STATE_LEARNING)
161+
if (state == BR_STATE_LEARNING) {
162+
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
159163
goto drop;
164+
}
160165

161166
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
162167
BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED);
@@ -223,7 +228,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
223228
out:
224229
return 0;
225230
drop:
226-
kfree_skb(skb);
231+
kfree_skb_reason(skb, reason);
227232
goto out;
228233
}
229234
EXPORT_SYMBOL_GPL(br_handle_frame_finish);
@@ -324,15 +329,18 @@ static int br_process_frame_type(struct net_bridge_port *p,
324329
*/
325330
static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
326331
{
332+
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
327333
struct net_bridge_port *p;
328334
struct sk_buff *skb = *pskb;
329335
const unsigned char *dest = eth_hdr(skb)->h_dest;
330336

331337
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
332338
return RX_HANDLER_PASS;
333339

334-
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
340+
if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) {
341+
reason = SKB_DROP_REASON_MAC_INVALID_SOURCE;
335342
goto drop;
343+
}
336344

337345
skb = skb_share_check(skb, GFP_ATOMIC);
338346
if (!skb)
@@ -374,6 +382,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
374382
return RX_HANDLER_PASS;
375383

376384
case 0x01: /* IEEE MAC (Pause) */
385+
reason = SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL;
377386
goto drop;
378387

379388
case 0x0E: /* 802.1AB LLDP */
@@ -423,8 +432,9 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
423432

424433
return nf_hook_bridge_pre(skb, pskb);
425434
default:
435+
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
426436
drop:
427-
kfree_skb(skb);
437+
kfree_skb_reason(skb, reason);
428438
}
429439
return RX_HANDLER_CONSUMED;
430440
}

0 commit comments

Comments
 (0)