Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ip6tnl: advertise tunnel param via rtnl

It is usefull for daemons that monitor link event to have the full parameters of
these interfaces when a rtnl message is sent.
It allows also to dump them via rtnetlink.

It is based on what is done for GRE tunnels.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Nicolas Dichtel and committed by
David S. Miller
c075b130 ba3e3f50

+60
+3
include/uapi/linux/if_tunnel.h
··· 44 44 IFLA_IPTUN_REMOTE, 45 45 IFLA_IPTUN_TTL, 46 46 IFLA_IPTUN_TOS, 47 + IFLA_IPTUN_ENCAP_LIMIT, 48 + IFLA_IPTUN_FLOWINFO, 49 + IFLA_IPTUN_FLAGS, 47 50 __IFLA_IPTUN_MAX, 48 51 }; 49 52 #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+57
net/ipv6/ip6_tunnel.c
··· 83 83 84 84 static int ip6_tnl_dev_init(struct net_device *dev); 85 85 static void ip6_tnl_dev_setup(struct net_device *dev); 86 + static struct rtnl_link_ops ip6_link_ops __read_mostly; 86 87 87 88 static int ip6_tnl_net_id __read_mostly; 88 89 struct ip6_tnl_net { ··· 300 299 goto failed_free; 301 300 302 301 strcpy(t->parms.name, dev->name); 302 + dev->rtnl_link_ops = &ip6_link_ops; 303 303 304 304 dev_hold(dev); 305 305 ip6_tnl_link(ip6n, t); ··· 1506 1504 return 0; 1507 1505 } 1508 1506 1507 + static size_t ip6_get_size(const struct net_device *dev) 1508 + { 1509 + return 1510 + /* IFLA_IPTUN_LINK */ 1511 + nla_total_size(4) + 1512 + /* IFLA_IPTUN_LOCAL */ 1513 + nla_total_size(sizeof(struct in6_addr)) + 1514 + /* IFLA_IPTUN_REMOTE */ 1515 + nla_total_size(sizeof(struct in6_addr)) + 1516 + /* IFLA_IPTUN_TTL */ 1517 + nla_total_size(1) + 1518 + /* IFLA_IPTUN_ENCAP_LIMIT */ 1519 + nla_total_size(1) + 1520 + /* IFLA_IPTUN_FLOWINFO */ 1521 + nla_total_size(4) + 1522 + /* IFLA_IPTUN_FLAGS */ 1523 + nla_total_size(4) + 1524 + 0; 1525 + } 1526 + 1527 + static int ip6_fill_info(struct sk_buff *skb, const struct net_device *dev) 1528 + { 1529 + struct ip6_tnl *tunnel = netdev_priv(dev); 1530 + struct __ip6_tnl_parm *parm = &tunnel->parms; 1531 + 1532 + if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || 1533 + nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr), 1534 + &parm->raddr) || 1535 + nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr), 1536 + &parm->laddr) || 1537 + nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) || 1538 + nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || 1539 + nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || 1540 + nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags)) 1541 + goto nla_put_failure; 1542 + return 0; 1543 + 1544 + nla_put_failure: 1545 + return -EMSGSIZE; 1546 + } 1547 + 1548 + static struct rtnl_link_ops ip6_link_ops __read_mostly = { 1549 + .kind = "ip6tnl", 1550 + .maxtype = IFLA_IPTUN_MAX, 1551 + .priv_size = sizeof(struct ip6_tnl), 1552 + .get_size = ip6_get_size, 1553 + .fill_info = ip6_fill_info, 1554 + }; 1555 + 1509 1556 static struct xfrm6_tunnel ip4ip6_handler __read_mostly = { 1510 1557 .handler = ip4ip6_rcv, 1511 1558 .err_handler = ip4ip6_err, ··· 1663 1612 pr_err("%s: can't register ip6ip6\n", __func__); 1664 1613 goto out_ip6ip6; 1665 1614 } 1615 + err = rtnl_link_register(&ip6_link_ops); 1616 + if (err < 0) 1617 + goto rtnl_link_failed; 1666 1618 1667 1619 return 0; 1668 1620 1621 + rtnl_link_failed: 1622 + xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); 1669 1623 out_ip6ip6: 1670 1624 xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); 1671 1625 out_ip4ip6: ··· 1685 1629 1686 1630 static void __exit ip6_tunnel_cleanup(void) 1687 1631 { 1632 + rtnl_link_unregister(&ip6_link_ops); 1688 1633 if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET)) 1689 1634 pr_info("%s: can't deregister ip4ip6\n", __func__); 1690 1635