ip_gre: add support for i/o_flags update
Subsystems (3)
cover ip_gre: add support for i/o_flags update
ip_gre is using as many ip_tunnel apis as possible, newlink works fine as gre would do it's own part in .ndo_init. But when changing link, ip_tunnel_changelink doesn't even update i/o_flags, and also the update of these flags would cause some other gre's properties need to be updated or recalculated.
These two patch are to add i/o_flags update and then do adjustment on some gre's properties according to the new i/o_flags.
Xin Long (2):
ip_gre: add the support for i/o_flags update via netlink
ip_gre: add the support for i/o_flags update via ioctl
net/ipv4/ip_gre.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-)
Signature · 1 line
2.1.0
PATCH 1/2 ip_gre: add the support for i/o_flags update via netlink
Now ip_gre is using ip_tunnel_changelink to update it's properties, but ip_tunnel_changelink in ip_tunnel doesn't update i/o_flags as a common function.
o_flags updates would cause that tunnel->tun_hlen / hlen and dev->mtu / needed_headroom need to be recalculated, and dev->(hw_)features need to be updated as well.
Therefore, we can't just add the update into ip_tunnel_update called in ip_tunnel_changelink, and it's also better not to touch ip_tunnel codes.
This patch updates i/o_flags and calls ipgre_link_update to recalculate these gre properties after ip_tunnel_changelink does the common update.
Note that since ipgre_link_update doesn't know the lower dev, it will update gre->hlen, dev->mtu and dev->needed_headroom with the value of 'new tun_hlen - old tun_hlen'. In this way, we can avoid many redundant codes, unlike ip6_gre.
--- net/ipv4/ip_gre.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-)
net/ipv4/ip_gre.c +37 -2
@@ -773,6 +773,30 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,return NETDEV_TX_OK ; } +static void ipgre_link_update (struct net_device *dev,bool set_mtu) +{ +struct ip_tunnel *tunnel =netdev_priv (dev); +int len; + + len = tunnel->tun_hlen; + tunnel->tun_hlen =gre_calc_hlen (tunnel->parms.o_flags); + len = tunnel->tun_hlen - len; + tunnel->hlen = tunnel->hlen + len; + + dev->needed_headroom = dev->needed_headroom + len; +if (set_mtu) + dev->mtu =max_t (int, dev->mtu - len,68 ); + +if (!(tunnel->parms.o_flags &TUNNEL_SEQ )) { +if (!(tunnel->parms.o_flags &TUNNEL_CSUM ) || + tunnel->encap.type ==TUNNEL_ENCAP_NONE ) { + dev->features |=NETIF_F_GSO_SOFTWARE ; + dev->hw_features |=NETIF_F_GSO_SOFTWARE ; + } + dev->features |=NETIF_F_LLTX ; + } +} +static int ipgre_tunnel_ioctl (struct net_device *dev,struct ifreq *ifr,int cmd) {
@@ -1307,9 +1331,9 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], struct netlink_ext_ack *extack) {struct ip_tunnel *t =netdev_priv (dev); -struct ip_tunnel_parm p;struct ip_tunnel_encap ipencap;__u32 fwmark = t->fwmark; +struct ip_tunnel_parm p;int err;if (ipgre_netlink_encap_parms (data, &ipencap)) {
@@ -1322,7 +1346,18 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], err =ipgre_netlink_parms (dev, data, tb, &p, &fwmark);if (err <0 )return err; -return ip_tunnel_changelink (dev, tb, &p, fwmark); + + err =ip_tunnel_changelink (dev, tb, &p, fwmark); +if (err <0 ) +return err; + + t->parms.i_flags = p.i_flags; + t->parms.o_flags = p.o_flags; + +if (strcmp (dev->rtnl_link_ops->kind,"erspan" )) +ipgre_link_update (dev, !tb[IFLA_MTU ]); + +return 0 ; }static size_t ipgre_get_size (const struct net_device *dev)
Signature · 1 line
2.1.0
PATCH 2/2 ip_gre: add the support for i/o_flags update via ioctl
As patch 'ip_gre: add the support for i/o_flags update via netlink' did for netlink, we also need to do the same job for these update via ioctl.
This patch is to update i/o_flags and call ipgre_link_update to recalculate these gre properties after ip_tunnel_ioctl does the common update.
--- net/ipv4/ip_gre.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
net/ipv4/ip_gre.c +16 -3
@@ -800,17 +800,19 @@ static void ipgre_link_update(struct net_device *dev, bool set_mtu)static int ipgre_tunnel_ioctl (struct net_device *dev,struct ifreq *ifr,int cmd) { -int err;struct ip_tunnel_parm p; +int err;if (copy_from_user (&p, ifr->ifr_ifru.ifru_data,sizeof (p)))return -EFAULT ; +if (cmd ==SIOCADDTUNNEL || cmd ==SIOCCHGTUNNEL ) {if (p.iph.version !=4 || p.iph.protocol !=IPPROTO_GRE || - p.iph.ihl !=5 || (p.iph.frag_off&htons (~IP_DF )) || - ((p.i_flags|p.o_flags)&(GRE_VERSION |GRE_ROUTING ))) + p.iph.ihl !=5 || (p.iph.frag_off &htons (~IP_DF )) || + ((p.i_flags | p.o_flags) & (GRE_VERSION |GRE_ROUTING )))return -EINVAL ; } + p.i_flags =gre_flags_to_tnl_flags (p.i_flags); p.o_flags =gre_flags_to_tnl_flags (p.o_flags);
@@ -818,11 +820,22 @@ static int ipgre_tunnel_ioctl(struct net_device *dev,if (err)return err; +if (cmd ==SIOCCHGTUNNEL ) { +struct ip_tunnel *t =netdev_priv (dev); + + t->parms.i_flags = p.i_flags; + t->parms.o_flags = p.o_flags; + +if (strcmp (dev->rtnl_link_ops->kind,"erspan" )) +ipgre_link_update (dev, true); + } + p.i_flags =gre_tnl_flags_to_gre_flags (p.i_flags); p.o_flags =gre_tnl_flags_to_gre_flags (p.o_flags);if (copy_to_user (ifr->ifr_ifru.ifru_data, &p,sizeof (p)))return -EFAULT ; +return 0 ; }
Signature · 1 line
2.1.0
Re: [PATCH net-next 1/2] ip_gre: add the support for i/o_flags update via netlink
In reply to Xin LongQuoted 77 lines · Xin Long
Now
ip_greis usingip_tunnel_changelinkto update it's properties, butip_tunnel_changelinkinip_tunneldoesn't update i/o_flags as a common function.
o_flagsupdates would cause thattunnel->tun_hlen/ hlen anddev->mtu/needed_headroomneed to be recalculated, and dev->(hw_)features need to be updated as well.Therefore, we can't just add the update into
ip_tunnel_updatecalled inip_tunnel_changelink, and it's also better not to touchip_tunnelcodes.This patch updates i/o_flags and calls
ipgre_link_updateto recalculate these gre properties afterip_tunnel_changelinkdoes the common update.Note that since
ipgre_link_updatedoesn't know the lower dev, it will updategre->hlen,dev->mtuanddev->needed_headroomwith the value of 'newtun_hlen- oldtun_hlen'. In this way, we can avoid many redundant codes, unlikeip6_gre.Reported-by Jianlin Shi <[email protected]>Signed-off-by Xin Long <[email protected]>--- net/ipv4/ip_gre.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-)net/ipv4/ip_gre.c +25
-2@@ -773,6 +773,30 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,return NETDEV_TX_OK ; } +static void ipgre_link_update (struct net_device *dev,bool set_mtu) +{ +struct ip_tunnel *tunnel =netdev_priv (dev); +int len; + + len = tunnel->tun_hlen; + tunnel->tun_hlen =gre_calc_hlen (tunnel->parms.o_flags); + len = tunnel->tun_hlen - len; + tunnel->hlen = tunnel->hlen + len; + + dev->needed_headroom = dev->needed_headroom + len; +if (set_mtu) + dev->mtu =max_t (int, dev->mtu - len,68 ); + +if (!(tunnel->parms.o_flags &TUNNEL_SEQ )) { +if (!(tunnel->parms.o_flags &TUNNEL_CSUM ) || + tunnel->encap.type ==TUNNEL_ENCAP_NONE ) { + dev->features |=NETIF_F_GSO_SOFTWARE ; + dev->hw_features |=NETIF_F_GSO_SOFTWARE ; + } + dev->features |=NETIF_F_LLTX ; + } +} +static int ipgre_tunnel_ioctl (struct net_device *dev,struct ifreq *ifr,int cmd) {@@ -1307,9 +1331,9 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], struct netlink_ext_ack *extack) {struct ip_tunnel *t =netdev_priv (dev); -struct ip_tunnel_parm p;struct ip_tunnel_encap ipencap;__u32 fwmark = t->fwmark; +struct ip_tunnel_parm p;int err;if (ipgre_netlink_encap_parms (data, &ipencap)) {@@ -1322,7 +1346,18 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], err =ipgre_netlink_parms (dev, data, tb, &p, &fwmark);if (err <0 )return err; -return ip_tunnel_changelink (dev, tb, &p, fwmark);
net/ipv4/ip_gre.c static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], · line 1358
Quoted 10 lines
net/ipv4/ip_gre.c +10
-0+ + err =ip_tunnel_changelink (dev, tb, &p, fwmark); +if (err <0 ) +return err; + + t->parms.i_flags = p.i_flags; + t->parms.o_flags = p.o_flags; + +if (strcmp (dev->rtnl_link_ops->kind,"erspan" )) +ipgre_link_update (dev, !tb[IFLA_MTU ]);
just to comment: ERSPAN does not need update because its GRE flag is fixed to SEQ.
Re: [PATCH net-next 2/2] ip_gre: add the support for i/o_flags update via ioctl
In reply to Xin LongQuoted 10 lines · Xin Long
As patch '
ip_gre: add the support for i/o_flags update via netlink' did for netlink, we also need to do the same job for these update via ioctl.This patch is to update i/o_flags and call
ipgre_link_updateto recalculate these gre properties afterip_tunnel_ioctldoes the common update.Signed-off-by Xin Long <[email protected]>---
LGTM.
David Miller
maintainerFrom: Xin Long <[email protected]>
Date: Tue, 7 Nov 2017 16:33:07 +0800
Quoted 8 lines
ip_greis using as manyip_tunnelapis as possible, newlink works fine as gre would do it's own part in .ndo_init. But when changing link,ip_tunnel_changelinkdoesn't even update i/o_flags, and also the update of these flags would cause some other gre's properties need to be updated or recalculated.These two patch are to add i/o_flags update and then do adjustment on some gre's properties according to the new i/o_flags.
Series applied, thank you.