net/core: Allow certain receives on inactive slave.
Allow a packet_type that specifies the exact device to receive even on an inactive bonding slave devices. This is important for some L2 protocols such as LLDP and FCoE. This can eventually be used for the bonding special cases as well. Signed-off-by: Joe Eykholt <jre@nuovasystems.com> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
cc9bd5cebc
commit
0d7a368123
1 changed files with 8 additions and 7 deletions
|
@ -2165,6 +2165,7 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct packet_type *ptype, *pt_prev;
|
struct packet_type *ptype, *pt_prev;
|
||||||
struct net_device *orig_dev;
|
struct net_device *orig_dev;
|
||||||
|
struct net_device *null_or_orig;
|
||||||
int ret = NET_RX_DROP;
|
int ret = NET_RX_DROP;
|
||||||
__be16 type;
|
__be16 type;
|
||||||
|
|
||||||
|
@ -2178,13 +2179,13 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||||
if (!skb->iif)
|
if (!skb->iif)
|
||||||
skb->iif = skb->dev->ifindex;
|
skb->iif = skb->dev->ifindex;
|
||||||
|
|
||||||
|
null_or_orig = NULL;
|
||||||
orig_dev = skb->dev;
|
orig_dev = skb->dev;
|
||||||
if (orig_dev->master) {
|
if (orig_dev->master) {
|
||||||
if (skb_bond_should_drop(skb)) {
|
if (skb_bond_should_drop(skb))
|
||||||
kfree_skb(skb);
|
null_or_orig = orig_dev; /* deliver only exact match */
|
||||||
return NET_RX_DROP;
|
else
|
||||||
}
|
skb->dev = orig_dev->master;
|
||||||
skb->dev = orig_dev->master;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__get_cpu_var(netdev_rx_stat).total++;
|
__get_cpu_var(netdev_rx_stat).total++;
|
||||||
|
@ -2209,7 +2210,7 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
list_for_each_entry_rcu(ptype, &ptype_all, list) {
|
list_for_each_entry_rcu(ptype, &ptype_all, list) {
|
||||||
if (!ptype->dev || ptype->dev == skb->dev) {
|
if (ptype->dev == null_or_orig || ptype->dev == skb->dev) {
|
||||||
if (pt_prev)
|
if (pt_prev)
|
||||||
ret = deliver_skb(skb, pt_prev, orig_dev);
|
ret = deliver_skb(skb, pt_prev, orig_dev);
|
||||||
pt_prev = ptype;
|
pt_prev = ptype;
|
||||||
|
@ -2234,7 +2235,7 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||||
list_for_each_entry_rcu(ptype,
|
list_for_each_entry_rcu(ptype,
|
||||||
&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
|
&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
|
||||||
if (ptype->type == type &&
|
if (ptype->type == type &&
|
||||||
(!ptype->dev || ptype->dev == skb->dev)) {
|
(ptype->dev == null_or_orig || ptype->dev == skb->dev)) {
|
||||||
if (pt_prev)
|
if (pt_prev)
|
||||||
ret = deliver_skb(skb, pt_prev, orig_dev);
|
ret = deliver_skb(skb, pt_prev, orig_dev);
|
||||||
pt_prev = ptype;
|
pt_prev = ptype;
|
||||||
|
|
Loading…
Reference in a new issue