This patch adds support for encapsulating IPv4/IPv6 within GENEVE. In order to use this, a new IFLA_GENEVE_INNER_PROTO_INHERIT flag needs to be provided at device creation. This property cannot be changed for the time being. In case IP traffic is received on a non-tun device the drop count is increased.
Unified · Split
| @@ -56,6 +56,7 @@ struct geneve_config { · 55 unmodified lines | |||
| 56 | bool use_udp6_rx_checksums; | 56 | bool use_udp6_rx_checksums; |
| 57 | bool ttl_inherit; | 57 | bool ttl_inherit; |
| 58 | enum ifla_geneve_df df; | 58 | enum ifla_geneve_df df; |
| 59 | bool inner_proto_inherit; | ||
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | /* Pseudo network device */ | 62 | /* Pseudo network device */ |
| @@ -251,17 +252,24 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, · 189 unmodified lines | |||
| 251 | } | 252 | } |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | skb_reset_mac_header(skb); | ||
| 255 | skb->protocol = eth_type_trans(skb, geneve->dev); | ||
| 256 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
| 257 | |||
| 258 | if (tun_dst) | 255 | if (tun_dst) |
| 259 | skb_dst_set(skb, &tun_dst->dst); | 256 | skb_dst_set(skb, &tun_dst->dst); |
| 260 | 257 | ||
| 261 | /* Ignore packet loops (and multicast echo) */ | 258 | if (gnvh->proto_type == htons(ETH_P_TEB)) { |
| 262 | if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) { | 259 | skb_reset_mac_header(skb); |
| 263 | geneve->dev->stats.rx_errors++; | 260 | skb->protocol = eth_type_trans(skb, geneve->dev); |
| 264 | goto drop; | 261 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); |
| 262 | |||
| 263 | /* Ignore packet loops (and multicast echo) */ | ||
| 264 | if (ether_addr_equal(eth_hdr(skb)->h_source, | ||
| 265 | geneve->dev->dev_addr)) { | ||
| 266 | geneve->dev->stats.rx_errors++; | ||
| 267 | goto drop; | ||
| 268 | } | ||
| 269 | } else { | ||
| 270 | skb_reset_mac_header(skb); | ||
| 271 | skb->dev = geneve->dev; | ||
| 272 | skb->pkt_type = PACKET_HOST; | ||
| 265 | } | 273 | } |
| 266 | 274 | ||
| 267 | oiph = skb_network_header(skb); | 275 | oiph = skb_network_header(skb); |
| @@ -345,6 +353,7 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) · 77 unmodified lines | |||
| 345 | struct genevehdr *geneveh; | 353 | struct genevehdr *geneveh; |
| 346 | struct geneve_dev *geneve; | 354 | struct geneve_dev *geneve; |
| 347 | struct geneve_sock *gs; | 355 | struct geneve_sock *gs; |
| 356 | __be16 inner_proto; | ||
| 348 | int opts_len; | 357 | int opts_len; |
| 349 | 358 | ||
| 350 | /* Need UDP and Geneve header to be present */ | 359 | /* Need UDP and Geneve header to be present */ |
| @@ -356,7 +365,11 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) · 5 unmodified lines | |||
| 356 | if (unlikely(geneveh->ver != GENEVE_VER)) | 365 | if (unlikely(geneveh->ver != GENEVE_VER)) |
| 357 | goto drop; | 366 | goto drop; |
| 358 | 367 | ||
| 359 | if (unlikely(geneveh->proto_type != htons(ETH_P_TEB))) | 368 | inner_proto = geneveh->proto_type; |
| 369 | |||
| 370 | if (unlikely((inner_proto != htons(ETH_P_TEB) && | ||
| 371 | inner_proto != htons(ETH_P_IP) && | ||
| 372 | inner_proto != htons(ETH_P_IPV6)))) | ||
| 360 | goto drop; | 373 | goto drop; |
| 361 | 374 | ||
| 362 | gs = rcu_dereference_sk_user_data(sk); | 375 | gs = rcu_dereference_sk_user_data(sk); |
| @@ -367,9 +380,14 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) · 4 unmodified lines | |||
| 367 | if (!geneve) | 380 | if (!geneve) |
| 368 | goto drop; | 381 | goto drop; |
| 369 | 382 | ||
| 383 | if (unlikely((!geneve->cfg.inner_proto_inherit && | ||
| 384 | inner_proto != htons(ETH_P_TEB)))) { | ||
| 385 | geneve->dev->stats.rx_dropped++; | ||
| 386 | goto drop; | ||
| 387 | } | ||
| 388 | |||
| 370 | opts_len = geneveh->opt_len * 4; | 389 | opts_len = geneveh->opt_len * 4; |
| 371 | if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, | 390 | if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, inner_proto, |
| 372 | htons(ETH_P_TEB), | ||
| 373 | !net_eq(geneve->net, dev_net(geneve->dev)))) { | 391 | !net_eq(geneve->net, dev_net(geneve->dev)))) { |
| 374 | geneve->dev->stats.rx_dropped++; | 392 | geneve->dev->stats.rx_dropped++; |
| 375 | goto drop; | 393 | goto drop; |
| @@ -717,7 +735,8 @@ static int geneve_stop(struct net_device *dev) · 341 unmodified lines | |||
| 717 | } | 735 | } |
| 718 | 736 | ||
| 719 | static void geneve_build_header(struct genevehdr *geneveh, | 737 | static void geneve_build_header(struct genevehdr *geneveh, |
| 720 | const struct ip_tunnel_info *info) | 738 | const struct ip_tunnel_info *info, |
| 739 | __be16 inner_proto) | ||
| 721 | { | 740 | { |
| 722 | geneveh->ver = GENEVE_VER; | 741 | geneveh->ver = GENEVE_VER; |
| 723 | geneveh->opt_len = info->options_len / 4; | 742 | geneveh->opt_len = info->options_len / 4; |
| @@ -725,7 +744,7 @@ static void geneve_build_header(struct genevehdr *geneveh, · 1 unmodified line | |||
| 725 | geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT); | 744 | geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT); |
| 726 | geneveh->rsvd1 = 0; | 745 | geneveh->rsvd1 = 0; |
| 727 | tunnel_id_to_vni(info->key.tun_id, geneveh->vni); | 746 | tunnel_id_to_vni(info->key.tun_id, geneveh->vni); |
| 728 | geneveh->proto_type = htons(ETH_P_TEB); | 747 | geneveh->proto_type = inner_proto; |
| 729 | geneveh->rsvd2 = 0; | 748 | geneveh->rsvd2 = 0; |
| 730 | 749 | ||
| 731 | if (info->key.tun_flags & TUNNEL_GENEVE_OPT) | 750 | if (info->key.tun_flags & TUNNEL_GENEVE_OPT) |
| @@ -734,10 +753,12 @@ static void geneve_build_header(struct genevehdr *geneveh, · 2 unmodified lines | |||
| 734 | 753 | ||
| 735 | static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb, | 754 | static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb, |
| 736 | const struct ip_tunnel_info *info, | 755 | const struct ip_tunnel_info *info, |
| 737 | bool xnet, int ip_hdr_len) | 756 | bool xnet, int ip_hdr_len, |
| 757 | bool inner_proto_inherit) | ||
| 738 | { | 758 | { |
| 739 | bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); | 759 | bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); |
| 740 | struct genevehdr *gnvh; | 760 | struct genevehdr *gnvh; |
| 761 | __be16 inner_proto; | ||
| 741 | int min_headroom; | 762 | int min_headroom; |
| 742 | int err; | 763 | int err; |
| 743 | 764 | ||
| @@ -755,8 +776,9 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb, · 11 unmodified lines | |||
| 755 | goto free_dst; | 776 | goto free_dst; |
| 756 | 777 | ||
| 757 | gnvh = __skb_push(skb, sizeof(*gnvh) + info->options_len); | 778 | gnvh = __skb_push(skb, sizeof(*gnvh) + info->options_len); |
| 758 | geneve_build_header(gnvh, info); | 779 | inner_proto = inner_proto_inherit ? skb->protocol : htons(ETH_P_TEB); |
| 759 | skb_set_inner_protocol(skb, htons(ETH_P_TEB)); | 780 | geneve_build_header(gnvh, info, inner_proto); |
| 781 | skb_set_inner_protocol(skb, inner_proto); | ||
| 760 | return 0; | 782 | return 0; |
| 761 | 783 | ||
| 762 | free_dst: | 784 | free_dst: |
| @@ -959,7 +981,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, · 196 unmodified lines | |||
| 959 | } | 981 | } |
| 960 | } | 982 | } |
| 961 | 983 | ||
| 962 | err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr)); | 984 | err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr), |
| 985 | geneve->cfg.inner_proto_inherit); | ||
| 963 | if (unlikely(err)) | 986 | if (unlikely(err)) |
| 964 | return err; | 987 | return err; |
| 965 | 988 | ||
| @@ -1038,7 +1061,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, · 72 unmodified lines | |||
| 1038 | ttl = key->ttl; | 1061 | ttl = key->ttl; |
| 1039 | ttl = ttl ? : ip6_dst_hoplimit(dst); | 1062 | ttl = ttl ? : ip6_dst_hoplimit(dst); |
| 1040 | } | 1063 | } |
| 1041 | err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr)); | 1064 | err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr), |
| 1065 | geneve->cfg.inner_proto_inherit); | ||
| 1042 | if (unlikely(err)) | 1066 | if (unlikely(err)) |
| 1043 | return err; | 1067 | return err; |
| 1044 | 1068 | ||
| @@ -1388,6 +1412,14 @@ static int geneve_configure(struct net *net, struct net_device *dev, · 343 unmodified lines | |||
| 1388 | dst_cache_reset(&geneve->cfg.info.dst_cache); | 1412 | dst_cache_reset(&geneve->cfg.info.dst_cache); |
| 1389 | memcpy(&geneve->cfg, cfg, sizeof(*cfg)); | 1413 | memcpy(&geneve->cfg, cfg, sizeof(*cfg)); |
| 1390 | 1414 | ||
| 1415 | if (geneve->cfg.inner_proto_inherit) { | ||
| 1416 | dev->header_ops = NULL; | ||
| 1417 | dev->type = ARPHRD_NONE; | ||
| 1418 | dev->hard_header_len = 0; | ||
| 1419 | dev->addr_len = 0; | ||
| 1420 | dev->flags = IFF_NOARP; | ||
| 1421 | } | ||
| 1422 | |||
| 1391 | err = register_netdevice(dev); | 1423 | err = register_netdevice(dev); |
| 1392 | if (err) | 1424 | if (err) |
| 1393 | return err; | 1425 | return err; |
| @@ -1561,10 +1593,18 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[], · 167 unmodified lines | |||
| 1561 | #endif | 1593 | #endif |
| 1562 | } | 1594 | } |
| 1563 | 1595 | ||
| 1596 | if (data[IFLA_GENEVE_INNER_PROTO_INHERIT]) { | ||
| 1597 | if (changelink) { | ||
| 1598 | attrtype = IFLA_GENEVE_INNER_PROTO_INHERIT; | ||
| 1599 | goto change_notsup; | ||
| 1600 | } | ||
| 1601 | cfg->inner_proto_inherit = true; | ||
| 1602 | } | ||
| 1603 | |||
| 1564 | return 0; | 1604 | return 0; |
| 1565 | change_notsup: | 1605 | change_notsup: |
| 1566 | NL_SET_ERR_MSG_ATTR(extack, data[attrtype], | 1606 | NL_SET_ERR_MSG_ATTR(extack, data[attrtype], |
| 1567 | "Changing VNI, Port, endpoint IP address family, external, and UDP checksum attributes are not supported"); | 1607 | "Changing VNI, Port, endpoint IP address family, external, inner_proto_inherit, and UDP checksum attributes are not supported"); |
| 1568 | return -EOPNOTSUPP; | 1608 | return -EOPNOTSUPP; |
| 1569 | } | 1609 | } |
| 1570 | 1610 | ||
| @@ -1799,6 +1839,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) · 228 unmodified lines | |||
| 1799 | if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit)) | 1839 | if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit)) |
| 1800 | goto nla_put_failure; | 1840 | goto nla_put_failure; |
| 1801 | 1841 | ||
| 1842 | if (geneve->cfg.inner_proto_inherit && | ||
| 1843 | nla_put_flag(skb, IFLA_GENEVE_INNER_PROTO_INHERIT)) | ||
| 1844 | goto nla_put_failure; | ||
| 1845 | |||
| 1802 | return 0; | 1846 | return 0; |
| 1803 | 1847 | ||
| 1804 | nla_put_failure: | 1848 | nla_put_failure: |
| @@ -842,6 +842,7 @@ enum { · 841 unmodified lines | |||
| 842 | IFLA_GENEVE_LABEL, | 842 | IFLA_GENEVE_LABEL, |
| 843 | IFLA_GENEVE_TTL_INHERIT, | 843 | IFLA_GENEVE_TTL_INHERIT, |
| 844 | IFLA_GENEVE_DF, | 844 | IFLA_GENEVE_DF, |
| 845 | IFLA_GENEVE_INNER_PROTO_INHERIT, | ||
| 845 | __IFLA_GENEVE_MAX | 846 | __IFLA_GENEVE_MAX |
| 846 | }; | 847 | }; |
| 847 | #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) | 848 | #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) |