History

net: geneve: support IPv4/IPv6 as inner protocol

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.

Eyal Birger committed 4 years ago

Commit 435fe1c1 parent 82192c42 files · +64 −19Browse files

Unified · Split

2 files
  1. drivers/net/geneve.c +63 −19
  2. include/uapi/linux/if_link.h +1 −0
drivers/net/geneve.c+63−19
@@ -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
719static void geneve_build_header(struct genevehdr *geneveh,737static 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
735static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,754static 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
762free_dst:784free_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#endif1593#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;
1565change_notsup:1605change_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
1804nla_put_failure:1848nla_put_failure:
include/uapi/linux/if_link.h+1−0
@@ -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_MAX846 __IFLA_GENEVE_MAX
846};847};
847#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)848#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)