diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 907d118..da78f0a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -78,6 +78,7 @@ struct wireless_dev; #define NET_RX_CN_MOD 3 /* Storm on its way! */ #define NET_RX_CN_HIGH 4 /* The storm is here */ #define NET_RX_BAD 5 /* packet dropped due to kernel error */ +#define NET_RX_CONSUMED 6 /* pkt is consumed, stop rx logic here. */ /* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It * indicates that the device will soon be dropping packets, or already drops diff --git a/net/core/dev.c b/net/core/dev.c index 0101178..d5024b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2105,6 +2105,10 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb, if (*pt_prev) { *ret = deliver_skb(skb, *pt_prev, orig_dev); *pt_prev = NULL; + if (*ret == NET_RX_CONSUMED) { + kfree_skb(skb); /* we made a copy in deliver_skb */ + return NULL; + } } return br_handle_frame_hook(port, skb); @@ -2128,6 +2132,10 @@ static inline struct sk_buff *handle_macvlan(struct sk_buff *skb, if (*pt_prev) { *ret = deliver_skb(skb, *pt_prev, orig_dev); *pt_prev = NULL; + if (*ret == NET_RX_CONSUMED) { + kfree_skb(skb); /* we made a copy in deliver_skb */ + return NULL; + } } return macvlan_handle_frame_hook(skb); } @@ -2185,6 +2193,10 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb, if (*pt_prev) { *ret = deliver_skb(skb, *pt_prev, orig_dev); *pt_prev = NULL; + if (*ret == NET_RX_CONSUMED) { + kfree_skb(skb); /* we made a copy in deliver_skb */ + return NULL; + } } else { /* Huh? Why does turning on AF_PACKET affect this? */ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); @@ -2300,8 +2312,13 @@ int netif_receive_skb(struct sk_buff *skb) list_for_each_entry_rcu(ptype, &ptype_all, list) { if (ptype->dev == null_or_orig || ptype->dev == skb->dev || ptype->dev == orig_dev) { - if (pt_prev) + if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); + if (ret == NET_RX_CONSUMED) { + kfree_skb(skb); /* we made a copy in deliver_skb */ + goto out; + } + } pt_prev = ptype; } } @@ -2336,8 +2353,13 @@ ncls: if (ptype->type == type && (ptype->dev == null_or_orig || ptype->dev == skb->dev || ptype->dev == orig_dev)) { - if (pt_prev) + if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); + if (ret == NET_RX_CONSUMED) { + kfree_skb(skb); /* we made a copy in deliver_skb */ + goto out; + } + } pt_prev = ptype; } }