diff options
-rw-r--r-- | drivers/net/bonding/bond_main.c | 22 | ||||
-rw-r--r-- | drivers/net/macvlan.c | 11 | ||||
-rw-r--r-- | include/linux/netdevice.h | 50 | ||||
-rw-r--r-- | include/linux/skbuff.h | 5 | ||||
-rw-r--r-- | net/bridge/br_input.c | 25 | ||||
-rw-r--r-- | net/bridge/br_private.h | 2 | ||||
-rw-r--r-- | net/core/dev.c | 21 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 |
8 files changed, 98 insertions, 39 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 04119b1e7cdb..27c413aa15da 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1480,20 +1480,23 @@ static bool bond_should_deliver_exact_match(struct sk_buff *skb, | |||
1480 | return false; | 1480 | return false; |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | static struct sk_buff *bond_handle_frame(struct sk_buff *skb) | 1483 | static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) |
1484 | { | 1484 | { |
1485 | struct sk_buff *skb = *pskb; | ||
1485 | struct slave *slave; | 1486 | struct slave *slave; |
1486 | struct net_device *bond_dev; | 1487 | struct net_device *bond_dev; |
1487 | struct bonding *bond; | 1488 | struct bonding *bond; |
1488 | 1489 | ||
1489 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
1490 | if (unlikely(!skb)) | ||
1491 | return NULL; | ||
1492 | |||
1493 | slave = bond_slave_get_rcu(skb->dev); | 1490 | slave = bond_slave_get_rcu(skb->dev); |
1494 | bond_dev = ACCESS_ONCE(slave->dev->master); | 1491 | bond_dev = ACCESS_ONCE(slave->dev->master); |
1495 | if (unlikely(!bond_dev)) | 1492 | if (unlikely(!bond_dev)) |
1496 | return skb; | 1493 | return RX_HANDLER_PASS; |
1494 | |||
1495 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
1496 | if (unlikely(!skb)) | ||
1497 | return RX_HANDLER_CONSUMED; | ||
1498 | |||
1499 | *pskb = skb; | ||
1497 | 1500 | ||
1498 | bond = netdev_priv(bond_dev); | 1501 | bond = netdev_priv(bond_dev); |
1499 | 1502 | ||
@@ -1501,8 +1504,7 @@ static struct sk_buff *bond_handle_frame(struct sk_buff *skb) | |||
1501 | slave->dev->last_rx = jiffies; | 1504 | slave->dev->last_rx = jiffies; |
1502 | 1505 | ||
1503 | if (bond_should_deliver_exact_match(skb, slave, bond)) { | 1506 | if (bond_should_deliver_exact_match(skb, slave, bond)) { |
1504 | skb->deliver_no_wcard = 1; | 1507 | return RX_HANDLER_EXACT; |
1505 | return skb; | ||
1506 | } | 1508 | } |
1507 | 1509 | ||
1508 | skb->dev = bond_dev; | 1510 | skb->dev = bond_dev; |
@@ -1514,12 +1516,12 @@ static struct sk_buff *bond_handle_frame(struct sk_buff *skb) | |||
1514 | if (unlikely(skb_cow_head(skb, | 1516 | if (unlikely(skb_cow_head(skb, |
1515 | skb->data - skb_mac_header(skb)))) { | 1517 | skb->data - skb_mac_header(skb)))) { |
1516 | kfree_skb(skb); | 1518 | kfree_skb(skb); |
1517 | return NULL; | 1519 | return RX_HANDLER_CONSUMED; |
1518 | } | 1520 | } |
1519 | memcpy(eth_hdr(skb)->h_dest, bond_dev->dev_addr, ETH_ALEN); | 1521 | memcpy(eth_hdr(skb)->h_dest, bond_dev->dev_addr, ETH_ALEN); |
1520 | } | 1522 | } |
1521 | 1523 | ||
1522 | return skb; | 1524 | return RX_HANDLER_ANOTHER; |
1523 | } | 1525 | } |
1524 | 1526 | ||
1525 | /* enslave device <slave> to bond device <master> */ | 1527 | /* enslave device <slave> to bond device <master> */ |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 497991bd3b64..5b37d3c191e4 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -152,9 +152,10 @@ static void macvlan_broadcast(struct sk_buff *skb, | |||
152 | } | 152 | } |
153 | 153 | ||
154 | /* called under rcu_read_lock() from netif_receive_skb */ | 154 | /* called under rcu_read_lock() from netif_receive_skb */ |
155 | static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | 155 | static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) |
156 | { | 156 | { |
157 | struct macvlan_port *port; | 157 | struct macvlan_port *port; |
158 | struct sk_buff *skb = *pskb; | ||
158 | const struct ethhdr *eth = eth_hdr(skb); | 159 | const struct ethhdr *eth = eth_hdr(skb); |
159 | const struct macvlan_dev *vlan; | 160 | const struct macvlan_dev *vlan; |
160 | const struct macvlan_dev *src; | 161 | const struct macvlan_dev *src; |
@@ -184,7 +185,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
184 | */ | 185 | */ |
185 | macvlan_broadcast(skb, port, src->dev, | 186 | macvlan_broadcast(skb, port, src->dev, |
186 | MACVLAN_MODE_VEPA); | 187 | MACVLAN_MODE_VEPA); |
187 | return skb; | 188 | return RX_HANDLER_PASS; |
188 | } | 189 | } |
189 | 190 | ||
190 | if (port->passthru) | 191 | if (port->passthru) |
@@ -192,12 +193,12 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
192 | else | 193 | else |
193 | vlan = macvlan_hash_lookup(port, eth->h_dest); | 194 | vlan = macvlan_hash_lookup(port, eth->h_dest); |
194 | if (vlan == NULL) | 195 | if (vlan == NULL) |
195 | return skb; | 196 | return RX_HANDLER_PASS; |
196 | 197 | ||
197 | dev = vlan->dev; | 198 | dev = vlan->dev; |
198 | if (unlikely(!(dev->flags & IFF_UP))) { | 199 | if (unlikely(!(dev->flags & IFF_UP))) { |
199 | kfree_skb(skb); | 200 | kfree_skb(skb); |
200 | return NULL; | 201 | return RX_HANDLER_CONSUMED; |
201 | } | 202 | } |
202 | len = skb->len + ETH_HLEN; | 203 | len = skb->len + ETH_HLEN; |
203 | skb = skb_share_check(skb, GFP_ATOMIC); | 204 | skb = skb_share_check(skb, GFP_ATOMIC); |
@@ -211,7 +212,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) | |||
211 | 212 | ||
212 | out: | 213 | out: |
213 | macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0); | 214 | macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0); |
214 | return NULL; | 215 | return RX_HANDLER_CONSUMED; |
215 | } | 216 | } |
216 | 217 | ||
217 | static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) | 218 | static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 604dbf5051d3..5eeb2cd3631c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -390,7 +390,55 @@ enum gro_result { | |||
390 | }; | 390 | }; |
391 | typedef enum gro_result gro_result_t; | 391 | typedef enum gro_result gro_result_t; |
392 | 392 | ||
393 | typedef struct sk_buff *rx_handler_func_t(struct sk_buff *skb); | 393 | /* |
394 | * enum rx_handler_result - Possible return values for rx_handlers. | ||
395 | * @RX_HANDLER_CONSUMED: skb was consumed by rx_handler, do not process it | ||
396 | * further. | ||
397 | * @RX_HANDLER_ANOTHER: Do another round in receive path. This is indicated in | ||
398 | * case skb->dev was changed by rx_handler. | ||
399 | * @RX_HANDLER_EXACT: Force exact delivery, no wildcard. | ||
400 | * @RX_HANDLER_PASS: Do nothing, passe the skb as if no rx_handler was called. | ||
401 | * | ||
402 | * rx_handlers are functions called from inside __netif_receive_skb(), to do | ||
403 | * special processing of the skb, prior to delivery to protocol handlers. | ||
404 | * | ||
405 | * Currently, a net_device can only have a single rx_handler registered. Trying | ||
406 | * to register a second rx_handler will return -EBUSY. | ||
407 | * | ||
408 | * To register a rx_handler on a net_device, use netdev_rx_handler_register(). | ||
409 | * To unregister a rx_handler on a net_device, use | ||
410 | * netdev_rx_handler_unregister(). | ||
411 | * | ||
412 | * Upon return, rx_handler is expected to tell __netif_receive_skb() what to | ||
413 | * do with the skb. | ||
414 | * | ||
415 | * If the rx_handler consumed to skb in some way, it should return | ||
416 | * RX_HANDLER_CONSUMED. This is appropriate when the rx_handler arranged for | ||
417 | * the skb to be delivered in some other ways. | ||
418 | * | ||
419 | * If the rx_handler changed skb->dev, to divert the skb to another | ||
420 | * net_device, it should return RX_HANDLER_ANOTHER. The rx_handler for the | ||
421 | * new device will be called if it exists. | ||
422 | * | ||
423 | * If the rx_handler consider the skb should be ignored, it should return | ||
424 | * RX_HANDLER_EXACT. The skb will only be delivered to protocol handlers that | ||
425 | * are registred on exact device (ptype->dev == skb->dev). | ||
426 | * | ||
427 | * If the rx_handler didn't changed skb->dev, but want the skb to be normally | ||
428 | * delivered, it should return RX_HANDLER_PASS. | ||
429 | * | ||
430 | * A device without a registered rx_handler will behave as if rx_handler | ||
431 | * returned RX_HANDLER_PASS. | ||
432 | */ | ||
433 | |||
434 | enum rx_handler_result { | ||
435 | RX_HANDLER_CONSUMED, | ||
436 | RX_HANDLER_ANOTHER, | ||
437 | RX_HANDLER_EXACT, | ||
438 | RX_HANDLER_PASS, | ||
439 | }; | ||
440 | typedef enum rx_handler_result rx_handler_result_t; | ||
441 | typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb); | ||
394 | 442 | ||
395 | extern void __napi_schedule(struct napi_struct *n); | 443 | extern void __napi_schedule(struct napi_struct *n); |
396 | 444 | ||
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 31f02d0b46a7..24cfa626931e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -388,10 +388,7 @@ struct sk_buff { | |||
388 | kmemcheck_bitfield_begin(flags2); | 388 | kmemcheck_bitfield_begin(flags2); |
389 | __u16 queue_mapping:16; | 389 | __u16 queue_mapping:16; |
390 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 390 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
391 | __u8 ndisc_nodetype:2, | 391 | __u8 ndisc_nodetype:2; |
392 | deliver_no_wcard:1; | ||
393 | #else | ||
394 | __u8 deliver_no_wcard:1; | ||
395 | #endif | 392 | #endif |
396 | __u8 ooo_okay:1; | 393 | __u8 ooo_okay:1; |
397 | kmemcheck_bitfield_end(flags2); | 394 | kmemcheck_bitfield_end(flags2); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 88e4aa9cb1f9..e2160792e1bc 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -139,21 +139,22 @@ static inline int is_link_local(const unsigned char *dest) | |||
139 | * Return NULL if skb is handled | 139 | * Return NULL if skb is handled |
140 | * note: already called with rcu_read_lock | 140 | * note: already called with rcu_read_lock |
141 | */ | 141 | */ |
142 | struct sk_buff *br_handle_frame(struct sk_buff *skb) | 142 | rx_handler_result_t br_handle_frame(struct sk_buff **pskb) |
143 | { | 143 | { |
144 | struct net_bridge_port *p; | 144 | struct net_bridge_port *p; |
145 | struct sk_buff *skb = *pskb; | ||
145 | const unsigned char *dest = eth_hdr(skb)->h_dest; | 146 | const unsigned char *dest = eth_hdr(skb)->h_dest; |
146 | br_should_route_hook_t *rhook; | 147 | br_should_route_hook_t *rhook; |
147 | 148 | ||
148 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) | 149 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) |
149 | return skb; | 150 | return RX_HANDLER_PASS; |
150 | 151 | ||
151 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 152 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
152 | goto drop; | 153 | goto drop; |
153 | 154 | ||
154 | skb = skb_share_check(skb, GFP_ATOMIC); | 155 | skb = skb_share_check(skb, GFP_ATOMIC); |
155 | if (!skb) | 156 | if (!skb) |
156 | return NULL; | 157 | return RX_HANDLER_CONSUMED; |
157 | 158 | ||
158 | p = br_port_get_rcu(skb->dev); | 159 | p = br_port_get_rcu(skb->dev); |
159 | 160 | ||
@@ -167,10 +168,12 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb) | |||
167 | goto forward; | 168 | goto forward; |
168 | 169 | ||
169 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 170 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
170 | NULL, br_handle_local_finish)) | 171 | NULL, br_handle_local_finish)) { |
171 | return NULL; /* frame consumed by filter */ | 172 | return RX_HANDLER_CONSUMED; /* consumed by filter */ |
172 | else | 173 | } else { |
173 | return skb; /* continue processing */ | 174 | *pskb = skb; |
175 | return RX_HANDLER_PASS; /* continue processing */ | ||
176 | } | ||
174 | } | 177 | } |
175 | 178 | ||
176 | forward: | 179 | forward: |
@@ -178,8 +181,10 @@ forward: | |||
178 | case BR_STATE_FORWARDING: | 181 | case BR_STATE_FORWARDING: |
179 | rhook = rcu_dereference(br_should_route_hook); | 182 | rhook = rcu_dereference(br_should_route_hook); |
180 | if (rhook) { | 183 | if (rhook) { |
181 | if ((*rhook)(skb)) | 184 | if ((*rhook)(skb)) { |
182 | return skb; | 185 | *pskb = skb; |
186 | return RX_HANDLER_PASS; | ||
187 | } | ||
183 | dest = eth_hdr(skb)->h_dest; | 188 | dest = eth_hdr(skb)->h_dest; |
184 | } | 189 | } |
185 | /* fall through */ | 190 | /* fall through */ |
@@ -194,5 +199,5 @@ forward: | |||
194 | drop: | 199 | drop: |
195 | kfree_skb(skb); | 200 | kfree_skb(skb); |
196 | } | 201 | } |
197 | return NULL; | 202 | return RX_HANDLER_CONSUMED; |
198 | } | 203 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f7afc364d777..19e2f46ed086 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -379,7 +379,7 @@ extern void br_features_recompute(struct net_bridge *br); | |||
379 | 379 | ||
380 | /* br_input.c */ | 380 | /* br_input.c */ |
381 | extern int br_handle_frame_finish(struct sk_buff *skb); | 381 | extern int br_handle_frame_finish(struct sk_buff *skb); |
382 | extern struct sk_buff *br_handle_frame(struct sk_buff *skb); | 382 | extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb); |
383 | 383 | ||
384 | /* br_ioctl.c */ | 384 | /* br_ioctl.c */ |
385 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 385 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
diff --git a/net/core/dev.c b/net/core/dev.c index 0d39032e9621..0b88eba97dab 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3070,6 +3070,8 @@ out: | |||
3070 | * on a failure. | 3070 | * on a failure. |
3071 | * | 3071 | * |
3072 | * The caller must hold the rtnl_mutex. | 3072 | * The caller must hold the rtnl_mutex. |
3073 | * | ||
3074 | * For a general description of rx_handler, see enum rx_handler_result. | ||
3073 | */ | 3075 | */ |
3074 | int netdev_rx_handler_register(struct net_device *dev, | 3076 | int netdev_rx_handler_register(struct net_device *dev, |
3075 | rx_handler_func_t *rx_handler, | 3077 | rx_handler_func_t *rx_handler, |
@@ -3129,6 +3131,7 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
3129 | rx_handler_func_t *rx_handler; | 3131 | rx_handler_func_t *rx_handler; |
3130 | struct net_device *orig_dev; | 3132 | struct net_device *orig_dev; |
3131 | struct net_device *null_or_dev; | 3133 | struct net_device *null_or_dev; |
3134 | bool deliver_exact = false; | ||
3132 | int ret = NET_RX_DROP; | 3135 | int ret = NET_RX_DROP; |
3133 | __be16 type; | 3136 | __be16 type; |
3134 | 3137 | ||
@@ -3181,18 +3184,22 @@ ncls: | |||
3181 | 3184 | ||
3182 | rx_handler = rcu_dereference(skb->dev->rx_handler); | 3185 | rx_handler = rcu_dereference(skb->dev->rx_handler); |
3183 | if (rx_handler) { | 3186 | if (rx_handler) { |
3184 | struct net_device *prev_dev; | ||
3185 | |||
3186 | if (pt_prev) { | 3187 | if (pt_prev) { |
3187 | ret = deliver_skb(skb, pt_prev, orig_dev); | 3188 | ret = deliver_skb(skb, pt_prev, orig_dev); |
3188 | pt_prev = NULL; | 3189 | pt_prev = NULL; |
3189 | } | 3190 | } |
3190 | prev_dev = skb->dev; | 3191 | switch (rx_handler(&skb)) { |
3191 | skb = rx_handler(skb); | 3192 | case RX_HANDLER_CONSUMED: |
3192 | if (!skb) | ||
3193 | goto out; | 3193 | goto out; |
3194 | if (skb->dev != prev_dev) | 3194 | case RX_HANDLER_ANOTHER: |
3195 | goto another_round; | 3195 | goto another_round; |
3196 | case RX_HANDLER_EXACT: | ||
3197 | deliver_exact = true; | ||
3198 | case RX_HANDLER_PASS: | ||
3199 | break; | ||
3200 | default: | ||
3201 | BUG(); | ||
3202 | } | ||
3196 | } | 3203 | } |
3197 | 3204 | ||
3198 | if (vlan_tx_tag_present(skb)) { | 3205 | if (vlan_tx_tag_present(skb)) { |
@@ -3210,7 +3217,7 @@ ncls: | |||
3210 | vlan_on_bond_hook(skb); | 3217 | vlan_on_bond_hook(skb); |
3211 | 3218 | ||
3212 | /* deliver only exact match when indicated */ | 3219 | /* deliver only exact match when indicated */ |
3213 | null_or_dev = skb->deliver_no_wcard ? skb->dev : NULL; | 3220 | null_or_dev = deliver_exact ? skb->dev : NULL; |
3214 | 3221 | ||
3215 | type = skb->protocol; | 3222 | type = skb->protocol; |
3216 | list_for_each_entry_rcu(ptype, | 3223 | list_for_each_entry_rcu(ptype, |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1eb526a848ff..801dd08908f9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -523,7 +523,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
523 | new->ip_summed = old->ip_summed; | 523 | new->ip_summed = old->ip_summed; |
524 | skb_copy_queue_mapping(new, old); | 524 | skb_copy_queue_mapping(new, old); |
525 | new->priority = old->priority; | 525 | new->priority = old->priority; |
526 | new->deliver_no_wcard = old->deliver_no_wcard; | ||
527 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 526 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
528 | new->ipvs_property = old->ipvs_property; | 527 | new->ipvs_property = old->ipvs_property; |
529 | #endif | 528 | #endif |