Commit 69ebaed0 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-GRE-mtu-changes'

Ido Schimmel says:

====================
mlxsw: Handle changes to MTU in GRE tunnels

Petr says:

When offloading GRE tunnels, the MTU setting is kept fixed after the
initial offload even as the slow-path configuration changed. Worse: the
offloaded MTU setting is actually just a transient value set at the time
of NETDEV_REGISTER of the tunnel. As of commit ffc2b6ee ("ip_gre:
fix IFLA_MTU ignored on NEWLINK"), that transient value is zero, and
unless there's e.g. a VRF migration that prompts re-offload, it stays at
zero, and all GRE packets end up trapping.

Thus, in patch #1, change the way the MTU is changed post-registration,
so that the full event protocol is observed. That way the drivers get to
see the change and have a chance to react.

In the remaining two patches, implement support for MTU change in mlxsw
driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f36b7534 68c3cd92
...@@ -1380,6 +1380,55 @@ mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp, ...@@ -1380,6 +1380,55 @@ mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp,
decap_fib_entry); decap_fib_entry);
} }
static int
mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
struct mlxsw_sp_vr *ul_vr, bool enable)
{
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
struct mlxsw_sp_rif *rif = &lb_rif->common;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
u32 saddr4;
switch (lb_cf.ul_protocol) {
case MLXSW_SP_L3_PROTO_IPV4:
saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
rif->rif_index, rif->vr_id, rif->dev->mtu);
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
ul_vr->id, saddr4, lb_cf.okey);
break;
case MLXSW_SP_L3_PROTO_IPV6:
return -EAFNOSUPPORT;
}
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
}
static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp,
struct net_device *ol_dev)
{
struct mlxsw_sp_ipip_entry *ipip_entry;
struct mlxsw_sp_rif_ipip_lb *lb_rif;
struct mlxsw_sp_vr *ul_vr;
int err = 0;
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
if (ipip_entry) {
lb_rif = ipip_entry->ol_lb;
ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
if (err)
goto out;
lb_rif->common.mtu = ol_dev->mtu;
}
out:
return err;
}
static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp *mlxsw_sp,
struct net_device *ol_dev) struct net_device *ol_dev)
{ {
...@@ -1660,6 +1709,8 @@ int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp, ...@@ -1660,6 +1709,8 @@ int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
extack = info->extack; extack = info->extack;
return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp, return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp,
ol_dev, extack); ol_dev, extack);
case NETDEV_CHANGEMTU:
return mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp, ol_dev);
} }
return 0; return 0;
} }
...@@ -6843,33 +6894,6 @@ mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif, ...@@ -6843,33 +6894,6 @@ mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
rif_lb->lb_config = params_lb->lb_config; rif_lb->lb_config = params_lb->lb_config;
} }
static int
mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
struct mlxsw_sp_vr *ul_vr, bool enable)
{
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
struct mlxsw_sp_rif *rif = &lb_rif->common;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
u32 saddr4;
switch (lb_cf.ul_protocol) {
case MLXSW_SP_L3_PROTO_IPV4:
saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
rif->rif_index, rif->vr_id, rif->dev->mtu);
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
ul_vr->id, saddr4, lb_cf.okey);
break;
case MLXSW_SP_L3_PROTO_IPV6:
return -EAFNOSUPPORT;
}
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
}
static int static int
mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
{ {
......
...@@ -362,13 +362,18 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, ...@@ -362,13 +362,18 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
struct ip_tunnel *nt; struct ip_tunnel *nt;
struct net_device *dev; struct net_device *dev;
int t_hlen; int t_hlen;
int mtu;
int err;
BUG_ON(!itn->fb_tunnel_dev); BUG_ON(!itn->fb_tunnel_dev);
dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms); dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms);
if (IS_ERR(dev)) if (IS_ERR(dev))
return ERR_CAST(dev); return ERR_CAST(dev);
dev->mtu = ip_tunnel_bind_dev(dev); mtu = ip_tunnel_bind_dev(dev);
err = dev_set_mtu(dev, mtu);
if (err)
goto err_dev_set_mtu;
nt = netdev_priv(dev); nt = netdev_priv(dev);
t_hlen = nt->hlen + sizeof(struct iphdr); t_hlen = nt->hlen + sizeof(struct iphdr);
...@@ -376,6 +381,10 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, ...@@ -376,6 +381,10 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net,
dev->max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen; dev->max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
ip_tunnel_add(itn, nt); ip_tunnel_add(itn, nt);
return nt; return nt;
err_dev_set_mtu:
unregister_netdevice(dev);
return ERR_PTR(err);
} }
int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
...@@ -1102,17 +1111,24 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], ...@@ -1102,17 +1111,24 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
nt->fwmark = fwmark; nt->fwmark = fwmark;
err = register_netdevice(dev); err = register_netdevice(dev);
if (err) if (err)
goto out; goto err_register_netdevice;
if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
eth_hw_addr_random(dev); eth_hw_addr_random(dev);
mtu = ip_tunnel_bind_dev(dev); mtu = ip_tunnel_bind_dev(dev);
if (!tb[IFLA_MTU]) if (!tb[IFLA_MTU]) {
dev->mtu = mtu; err = dev_set_mtu(dev, mtu);
if (err)
goto err_dev_set_mtu;
}
ip_tunnel_add(itn, nt); ip_tunnel_add(itn, nt);
out: return 0;
err_dev_set_mtu:
unregister_netdevice(dev);
err_register_netdevice:
return err; return err;
} }
EXPORT_SYMBOL_GPL(ip_tunnel_newlink); EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment