From: Mahesh Bandewar <mahe...@google.com> Current packet processing from IPtables perspective is asymmetric for IPvlan L3 mode. On egress path, packets hit LOCAL_OUT and POST_ROUTING hooks in slave-ns as well as master's ns however during ingress path, LOCAL_IN and PRE_ROUTING hooks are hit only in slave's ns. L3 mode is restrictive and uses master's L3 for packet processing, so it does not make sense to skip these hooks in ingress path in master's ns.
The changes in this patch nominates master-dev to be the device for L3 ingress processing when skb device is the IPvlan slave. Since master device is used for L3 processing, the IPT hooks are hit in master's ns making the packet processing symmetric. The other minor change this patch does to add a force parameter for set_port_mode() to ensure correct settings are set during the device initialization phase. Signed-off-by: Mahesh Bandewar <mahe...@google.com> CC: Eric Dumazet <eduma...@google.com> CC: Tim Hockin <thoc...@google.com> CC: Alex Pollitt <alex.poll...@metaswitch.com> CC: Matthew Dupre <matthew.du...@metaswitch.com> --- drivers/net/ipvlan/ipvlan_main.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 5802b9025765..734c25e52c60 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -14,16 +14,19 @@ static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) ipvlan->dev->mtu = dev->mtu - ipvlan->mtu_adj; } -static void ipvlan_set_port_mode(struct ipvl_port *port, u16 nval) +static void ipvlan_set_port_mode(struct ipvl_port *port, u16 nval, bool force) { struct ipvl_dev *ipvlan; - if (port->mode != nval) { + if (port->mode != nval || force) { list_for_each_entry(ipvlan, &port->ipvlans, pnode) { - if (nval == IPVLAN_MODE_L3) + if (nval == IPVLAN_MODE_L3) { ipvlan->dev->flags |= IFF_NOARP; - else + ipvlan->dev->l3_dev = port->dev; + } else { ipvlan->dev->flags &= ~IFF_NOARP; + ipvlan->dev->l3_dev = ipvlan->dev; + } } port->mode = nval; } @@ -392,7 +395,7 @@ static int ipvlan_nl_changelink(struct net_device *dev, if (data && data[IFLA_IPVLAN_MODE]) { u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]); - ipvlan_set_port_mode(port, nmode); + ipvlan_set_port_mode(port, nmode, false); } return 0; } @@ -479,7 +482,6 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, memcpy(dev->dev_addr, phy_dev->dev_addr, ETH_ALEN); dev->priv_flags |= IFF_IPVLAN_SLAVE; - port->count += 1; err = register_netdevice(dev); if (err < 0) @@ -490,7 +492,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, goto ipvlan_destroy_port; list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans); - ipvlan_set_port_mode(port, mode); + ipvlan_set_port_mode(port, mode, true); netif_stacked_transfer_operstate(phy_dev, dev); return 0; -- 2.7.0.rc3.207.g0ac5344