mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 02:53:36 +02:00
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/20241219163606.717758-1-rrendec@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
a6ac667467
|
|
@ -2798,7 +2798,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
dev_dstats_tx_dropped(dev);
|
||||
vxlan_vnifilter_count(vxlan, vni, NULL,
|
||||
VXLAN_VNI_STATS_TX_DROPS, 0);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -2821,7 +2821,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
if (fdst)
|
||||
vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
|
||||
else
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
|
|
|||
|
|
@ -1712,7 +1712,7 @@ netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
|
|||
vxlan_xmit_one(skb, vxlan->dev, src_vni,
|
||||
rcu_dereference(fremote->rd), false);
|
||||
else
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,11 +106,13 @@
|
|||
FN(VXLAN_VNI_NOT_FOUND) \
|
||||
FN(MAC_INVALID_SOURCE) \
|
||||
FN(VXLAN_ENTRY_EXISTS) \
|
||||
FN(VXLAN_NO_REMOTE) \
|
||||
FN(NO_TX_TARGET) \
|
||||
FN(IP_TUNNEL_ECN) \
|
||||
FN(TUNNEL_TXINFO) \
|
||||
FN(LOCAL_MAC) \
|
||||
FN(ARP_PVLAN_DISABLE) \
|
||||
FN(MAC_IEEE_MAC_CONTROL) \
|
||||
FN(BRIDGE_INGRESS_STP_STATE) \
|
||||
FNe(MAX)
|
||||
|
||||
/**
|
||||
|
|
@ -497,8 +499,8 @@ enum skb_drop_reason {
|
|||
* entry or an entry pointing to a nexthop.
|
||||
*/
|
||||
SKB_DROP_REASON_VXLAN_ENTRY_EXISTS,
|
||||
/** @SKB_DROP_REASON_VXLAN_NO_REMOTE: no remote found for xmit */
|
||||
SKB_DROP_REASON_VXLAN_NO_REMOTE,
|
||||
/** @SKB_DROP_REASON_NO_TX_TARGET: no target found for xmit */
|
||||
SKB_DROP_REASON_NO_TX_TARGET,
|
||||
/**
|
||||
* @SKB_DROP_REASON_IP_TUNNEL_ECN: skb is dropped according to
|
||||
* RFC 6040 4.2, see __INET_ECN_decapsulate() for detail.
|
||||
|
|
@ -520,6 +522,16 @@ enum skb_drop_reason {
|
|||
* enabled.
|
||||
*/
|
||||
SKB_DROP_REASON_ARP_PVLAN_DISABLE,
|
||||
/**
|
||||
* @SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL: the destination MAC address
|
||||
* is an IEEE MAC Control address.
|
||||
*/
|
||||
SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL,
|
||||
/**
|
||||
* @SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE: the STP state of the
|
||||
* ingress bridge port does not allow frames to be forwarded.
|
||||
*/
|
||||
SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE,
|
||||
/**
|
||||
* @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
|
||||
* shouldn't be used as a real 'reason' - only for tracing code gen
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
|||
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
|
||||
u16 vid)
|
||||
{
|
||||
enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
|
||||
struct net_bridge_port *prev = NULL;
|
||||
struct net_bridge_port *p;
|
||||
|
||||
|
|
@ -234,8 +235,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
|||
continue;
|
||||
|
||||
prev = maybe_deliver(prev, p, skb, local_orig);
|
||||
if (IS_ERR(prev))
|
||||
if (IS_ERR(prev)) {
|
||||
reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
|
||||
SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
|
|
@ -249,7 +253,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
|||
|
||||
out:
|
||||
if (!local_rcv)
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
||||
|
|
@ -289,6 +293,7 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
|
|||
struct net_bridge_mcast *brmctx,
|
||||
bool local_rcv, bool local_orig)
|
||||
{
|
||||
enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
|
||||
struct net_bridge_port *prev = NULL;
|
||||
struct net_bridge_port_group *p;
|
||||
bool allow_mode_include = true;
|
||||
|
|
@ -329,8 +334,11 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
|
|||
}
|
||||
|
||||
prev = maybe_deliver(prev, port, skb, local_orig);
|
||||
if (IS_ERR(prev))
|
||||
if (IS_ERR(prev)) {
|
||||
reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
|
||||
SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
goto out;
|
||||
}
|
||||
delivered:
|
||||
if ((unsigned long)lport >= (unsigned long)port)
|
||||
p = rcu_dereference(p->next);
|
||||
|
|
@ -349,6 +357,6 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
|
|||
|
||||
out:
|
||||
if (!local_rcv)
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
|
|||
/* note: already called with rcu_read_lock */
|
||||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
|
||||
enum br_pkt_type pkt_type = BR_PKT_UNICAST;
|
||||
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
|
|||
if (br_mst_is_enabled(br)) {
|
||||
state = BR_STATE_FORWARDING;
|
||||
} else {
|
||||
if (p->state == BR_STATE_DISABLED)
|
||||
if (p->state == BR_STATE_DISABLED) {
|
||||
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
state = p->state;
|
||||
}
|
||||
|
|
@ -155,8 +158,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
|||
}
|
||||
}
|
||||
|
||||
if (state == BR_STATE_LEARNING)
|
||||
if (state == BR_STATE_LEARNING) {
|
||||
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
|
||||
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
|
|||
out:
|
||||
return 0;
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
goto out;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(br_handle_frame_finish);
|
||||
|
|
@ -324,6 +329,7 @@ static int br_process_frame_type(struct net_bridge_port *p,
|
|||
*/
|
||||
static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
||||
{
|
||||
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
|
||||
struct net_bridge_port *p;
|
||||
struct sk_buff *skb = *pskb;
|
||||
const unsigned char *dest = eth_hdr(skb)->h_dest;
|
||||
|
|
@ -331,8 +337,10 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
|||
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
|
||||
return RX_HANDLER_PASS;
|
||||
|
||||
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
||||
if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) {
|
||||
reason = SKB_DROP_REASON_MAC_INVALID_SOURCE;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
|
|
@ -374,6 +382,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
|||
return RX_HANDLER_PASS;
|
||||
|
||||
case 0x01: /* IEEE MAC (Pause) */
|
||||
reason = SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL;
|
||||
goto drop;
|
||||
|
||||
case 0x0E: /* 802.1AB LLDP */
|
||||
|
|
@ -423,8 +432,9 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
|||
|
||||
return nf_hook_bridge_pre(skb, pskb);
|
||||
default:
|
||||
reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
kfree_skb_reason(skb, reason);
|
||||
}
|
||||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user