aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-09-17 15:25:59 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-19 17:15:32 -0400
commit14909664e4e192f4c6f6fcdccd9919af7cf783ab (patch)
treee18f5d4fd6133197cfe3c3b7e7da49ed7b5cd657 /net/ipv6
parent56328486539ddd07cbaafec7a542a2c8a3043623 (diff)
sit: Setup and TX path for sit/UDP foo-over-udp encapsulation
Added netlink handling of IP tunnel encapulation paramters, properly adjust MTU for encapsulation. Added ip_tunnel_encap call to ipip6_tunnel_xmit to actually perform FOU encapsulation. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/sit.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 86e3fa81f85e..db75809ab843 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -822,6 +822,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
822 int addr_type; 822 int addr_type;
823 u8 ttl; 823 u8 ttl;
824 int err; 824 int err;
825 u8 protocol = IPPROTO_IPV6;
826 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
825 827
826 if (skb->protocol != htons(ETH_P_IPV6)) 828 if (skb->protocol != htons(ETH_P_IPV6))
827 goto tx_error; 829 goto tx_error;
@@ -911,8 +913,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
911 goto tx_error; 913 goto tx_error;
912 } 914 }
913 915
916 skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
917 if (IS_ERR(skb)) {
918 ip_rt_put(rt);
919 goto out;
920 }
921
914 if (df) { 922 if (df) {
915 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); 923 mtu = dst_mtu(&rt->dst) - t_hlen;
916 924
917 if (mtu < 68) { 925 if (mtu < 68) {
918 dev->stats.collisions++; 926 dev->stats.collisions++;
@@ -947,7 +955,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
947 /* 955 /*
948 * Okay, now see if we can stuff it in the buffer as-is. 956 * Okay, now see if we can stuff it in the buffer as-is.
949 */ 957 */
950 max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr); 958 max_headroom = LL_RESERVED_SPACE(tdev) + t_hlen;
951 959
952 if (skb_headroom(skb) < max_headroom || skb_shared(skb) || 960 if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
953 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { 961 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
@@ -969,14 +977,13 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
969 ttl = iph6->hop_limit; 977 ttl = iph6->hop_limit;
970 tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); 978 tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
971 979
972 skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); 980 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) {
973 if (IS_ERR(skb)) {
974 ip_rt_put(rt); 981 ip_rt_put(rt);
975 goto out; 982 goto tx_error;
976 } 983 }
977 984
978 err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, 985 err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr,
979 IPPROTO_IPV6, tos, ttl, df, 986 protocol, tos, ttl, df,
980 !net_eq(tunnel->net, dev_net(dev))); 987 !net_eq(tunnel->net, dev_net(dev)));
981 iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 988 iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
982 return NETDEV_TX_OK; 989 return NETDEV_TX_OK;
@@ -1059,8 +1066,10 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
1059 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); 1066 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
1060 1067
1061 if (tdev) { 1068 if (tdev) {
1069 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1070
1062 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); 1071 dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
1063 dev->mtu = tdev->mtu - sizeof(struct iphdr); 1072 dev->mtu = tdev->mtu - t_hlen;
1064 if (dev->mtu < IPV6_MIN_MTU) 1073 if (dev->mtu < IPV6_MIN_MTU)
1065 dev->mtu = IPV6_MIN_MTU; 1074 dev->mtu = IPV6_MIN_MTU;
1066 } 1075 }
@@ -1307,7 +1316,10 @@ done:
1307 1316
1308static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) 1317static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
1309{ 1318{
1310 if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr)) 1319 struct ip_tunnel *tunnel = netdev_priv(dev);
1320 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1321
1322 if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - t_hlen)
1311 return -EINVAL; 1323 return -EINVAL;
1312 dev->mtu = new_mtu; 1324 dev->mtu = new_mtu;
1313 return 0; 1325 return 0;
@@ -1338,12 +1350,15 @@ static void ipip6_dev_free(struct net_device *dev)
1338 1350
1339static void ipip6_tunnel_setup(struct net_device *dev) 1351static void ipip6_tunnel_setup(struct net_device *dev)
1340{ 1352{
1353 struct ip_tunnel *tunnel = netdev_priv(dev);
1354 int t_hlen = tunnel->hlen + sizeof(struct iphdr);
1355
1341 dev->netdev_ops = &ipip6_netdev_ops; 1356 dev->netdev_ops = &ipip6_netdev_ops;
1342 dev->destructor = ipip6_dev_free; 1357 dev->destructor = ipip6_dev_free;
1343 1358
1344 dev->type = ARPHRD_SIT; 1359 dev->type = ARPHRD_SIT;
1345 dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); 1360 dev->hard_header_len = LL_MAX_HEADER + t_hlen;
1346 dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); 1361 dev->mtu = ETH_DATA_LEN - t_hlen;
1347 dev->flags = IFF_NOARP; 1362 dev->flags = IFF_NOARP;
1348 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; 1363 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
1349 dev->iflink = 0; 1364 dev->iflink = 0;
@@ -1466,6 +1481,40 @@ static void ipip6_netlink_parms(struct nlattr *data[],
1466 1481
1467} 1482}
1468 1483
1484/* This function returns true when ENCAP attributes are present in the nl msg */
1485static bool ipip6_netlink_encap_parms(struct nlattr *data[],
1486 struct ip_tunnel_encap *ipencap)
1487{
1488 bool ret = false;
1489
1490 memset(ipencap, 0, sizeof(*ipencap));
1491
1492 if (!data)
1493 return ret;
1494
1495 if (data[IFLA_IPTUN_ENCAP_TYPE]) {
1496 ret = true;
1497 ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
1498 }
1499
1500 if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
1501 ret = true;
1502 ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
1503 }
1504
1505 if (data[IFLA_IPTUN_ENCAP_SPORT]) {
1506 ret = true;
1507 ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]);
1508 }
1509
1510 if (data[IFLA_IPTUN_ENCAP_DPORT]) {
1511 ret = true;
1512 ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]);
1513 }
1514
1515 return ret;
1516}
1517
1469#ifdef CONFIG_IPV6_SIT_6RD 1518#ifdef CONFIG_IPV6_SIT_6RD
1470/* This function returns true when 6RD attributes are present in the nl msg */ 1519/* This function returns true when 6RD attributes are present in the nl msg */
1471static bool ipip6_netlink_6rd_parms(struct nlattr *data[], 1520static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
@@ -1509,12 +1558,20 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev,
1509{ 1558{
1510 struct net *net = dev_net(dev); 1559 struct net *net = dev_net(dev);
1511 struct ip_tunnel *nt; 1560 struct ip_tunnel *nt;
1561 struct ip_tunnel_encap ipencap;
1512#ifdef CONFIG_IPV6_SIT_6RD 1562#ifdef CONFIG_IPV6_SIT_6RD
1513 struct ip_tunnel_6rd ip6rd; 1563 struct ip_tunnel_6rd ip6rd;
1514#endif 1564#endif
1515 int err; 1565 int err;
1516 1566
1517 nt = netdev_priv(dev); 1567 nt = netdev_priv(dev);
1568
1569 if (ipip6_netlink_encap_parms(data, &ipencap)) {
1570 err = ip_tunnel_encap_setup(nt, &ipencap);
1571 if (err < 0)
1572 return err;
1573 }
1574
1518 ipip6_netlink_parms(data, &nt->parms); 1575 ipip6_netlink_parms(data, &nt->parms);
1519 1576
1520 if (ipip6_tunnel_locate(net, &nt->parms, 0)) 1577 if (ipip6_tunnel_locate(net, &nt->parms, 0))
@@ -1537,15 +1594,23 @@ static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
1537{ 1594{
1538 struct ip_tunnel *t = netdev_priv(dev); 1595 struct ip_tunnel *t = netdev_priv(dev);
1539 struct ip_tunnel_parm p; 1596 struct ip_tunnel_parm p;
1597 struct ip_tunnel_encap ipencap;
1540 struct net *net = t->net; 1598 struct net *net = t->net;
1541 struct sit_net *sitn = net_generic(net, sit_net_id); 1599 struct sit_net *sitn = net_generic(net, sit_net_id);
1542#ifdef CONFIG_IPV6_SIT_6RD 1600#ifdef CONFIG_IPV6_SIT_6RD
1543 struct ip_tunnel_6rd ip6rd; 1601 struct ip_tunnel_6rd ip6rd;
1544#endif 1602#endif
1603 int err;
1545 1604
1546 if (dev == sitn->fb_tunnel_dev) 1605 if (dev == sitn->fb_tunnel_dev)
1547 return -EINVAL; 1606 return -EINVAL;
1548 1607
1608 if (ipip6_netlink_encap_parms(data, &ipencap)) {
1609 err = ip_tunnel_encap_setup(t, &ipencap);
1610 if (err < 0)
1611 return err;
1612 }
1613
1549 ipip6_netlink_parms(data, &p); 1614 ipip6_netlink_parms(data, &p);
1550 1615
1551 if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) || 1616 if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
@@ -1599,6 +1664,14 @@ static size_t ipip6_get_size(const struct net_device *dev)
1599 /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */ 1664 /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
1600 nla_total_size(2) + 1665 nla_total_size(2) +
1601#endif 1666#endif
1667 /* IFLA_IPTUN_ENCAP_TYPE */
1668 nla_total_size(2) +
1669 /* IFLA_IPTUN_ENCAP_FLAGS */
1670 nla_total_size(2) +
1671 /* IFLA_IPTUN_ENCAP_SPORT */
1672 nla_total_size(2) +
1673 /* IFLA_IPTUN_ENCAP_DPORT */
1674 nla_total_size(2) +
1602 0; 1675 0;
1603} 1676}
1604 1677
@@ -1630,6 +1703,16 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
1630 goto nla_put_failure; 1703 goto nla_put_failure;
1631#endif 1704#endif
1632 1705
1706 if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
1707 tunnel->encap.type) ||
1708 nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT,
1709 tunnel->encap.sport) ||
1710 nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT,
1711 tunnel->encap.dport) ||
1712 nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
1713 tunnel->encap.dport))
1714 goto nla_put_failure;
1715
1633 return 0; 1716 return 0;
1634 1717
1635nla_put_failure: 1718nla_put_failure:
@@ -1651,6 +1734,10 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
1651 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 }, 1734 [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NLA_U16 },
1652 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 }, 1735 [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
1653#endif 1736#endif
1737 [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 },
1738 [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
1739 [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
1740 [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
1654}; 1741};
1655 1742
1656static void ipip6_dellink(struct net_device *dev, struct list_head *head) 1743static void ipip6_dellink(struct net_device *dev, struct list_head *head)