Skip to content

Commit d0619cb

Browse files
committed
net: geneve: support IPv4/IPv6 as inner protocol
jira LE-1733 bugfix-pre geneve_fixes commit 435fe1c 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. Signed-off-by: Eyal Birger <eyal.birger@gmail.com> Link: https://lore.kernel.org/r/20220316061557.431872-1-eyal.birger@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> (cherry picked from commit 435fe1c) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent eae2d23 commit d0619cb

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

drivers/net/geneve.c

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct geneve_config {
5656
bool use_udp6_rx_checksums;
5757
bool ttl_inherit;
5858
enum ifla_geneve_df df;
59+
bool inner_proto_inherit;
5960
};
6061

6162
/* Pseudo network device */
@@ -251,17 +252,24 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
251252
}
252253
}
253254

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-
258255
if (tun_dst)
259256
skb_dst_set(skb, &tun_dst->dst);
260257

261-
/* Ignore packet loops (and multicast echo) */
262-
if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) {
263-
geneve->dev->stats.rx_errors++;
264-
goto drop;
258+
if (gnvh->proto_type == htons(ETH_P_TEB)) {
259+
skb_reset_mac_header(skb);
260+
skb->protocol = eth_type_trans(skb, geneve->dev);
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;
265273
}
266274

267275
oiph = skb_network_header(skb);
@@ -345,6 +353,7 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
345353
struct genevehdr *geneveh;
346354
struct geneve_dev *geneve;
347355
struct geneve_sock *gs;
356+
__be16 inner_proto;
348357
int opts_len;
349358

350359
/* 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)
356365
if (unlikely(geneveh->ver != GENEVE_VER))
357366
goto drop;
358367

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))))
360373
goto drop;
361374

362375
gs = rcu_dereference_sk_user_data(sk);
@@ -367,9 +380,14 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
367380
if (!geneve)
368381
goto drop;
369382

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+
370389
opts_len = geneveh->opt_len * 4;
371-
if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
372-
htons(ETH_P_TEB),
390+
if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, inner_proto,
373391
!net_eq(geneve->net, dev_net(geneve->dev)))) {
374392
geneve->dev->stats.rx_dropped++;
375393
goto drop;
@@ -723,15 +741,16 @@ static int geneve_stop(struct net_device *dev)
723741
}
724742

725743
static void geneve_build_header(struct genevehdr *geneveh,
726-
const struct ip_tunnel_info *info)
744+
const struct ip_tunnel_info *info,
745+
__be16 inner_proto)
727746
{
728747
geneveh->ver = GENEVE_VER;
729748
geneveh->opt_len = info->options_len / 4;
730749
geneveh->oam = !!(info->key.tun_flags & TUNNEL_OAM);
731750
geneveh->critical = !!(info->key.tun_flags & TUNNEL_CRIT_OPT);
732751
geneveh->rsvd1 = 0;
733752
tunnel_id_to_vni(info->key.tun_id, geneveh->vni);
734-
geneveh->proto_type = htons(ETH_P_TEB);
753+
geneveh->proto_type = inner_proto;
735754
geneveh->rsvd2 = 0;
736755

737756
if (info->key.tun_flags & TUNNEL_GENEVE_OPT)
@@ -740,10 +759,12 @@ static void geneve_build_header(struct genevehdr *geneveh,
740759

741760
static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
742761
const struct ip_tunnel_info *info,
743-
bool xnet, int ip_hdr_len)
762+
bool xnet, int ip_hdr_len,
763+
bool inner_proto_inherit)
744764
{
745765
bool udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
746766
struct genevehdr *gnvh;
767+
__be16 inner_proto;
747768
int min_headroom;
748769
int err;
749770

@@ -761,8 +782,9 @@ static int geneve_build_skb(struct dst_entry *dst, struct sk_buff *skb,
761782
goto free_dst;
762783

763784
gnvh = __skb_push(skb, sizeof(*gnvh) + info->options_len);
764-
geneve_build_header(gnvh, info);
765-
skb_set_inner_protocol(skb, htons(ETH_P_TEB));
785+
inner_proto = inner_proto_inherit ? skb->protocol : htons(ETH_P_TEB);
786+
geneve_build_header(gnvh, info, inner_proto);
787+
skb_set_inner_protocol(skb, inner_proto);
766788
return 0;
767789

768790
free_dst:
@@ -969,7 +991,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
969991
}
970992
}
971993

972-
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
994+
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr),
995+
geneve->cfg.inner_proto_inherit);
973996
if (unlikely(err))
974997
return err;
975998

@@ -1048,7 +1071,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
10481071
ttl = key->ttl;
10491072
ttl = ttl ? : ip6_dst_hoplimit(dst);
10501073
}
1051-
err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr));
1074+
err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr),
1075+
geneve->cfg.inner_proto_inherit);
10521076
if (unlikely(err))
10531077
return err;
10541078

@@ -1398,6 +1422,14 @@ static int geneve_configure(struct net *net, struct net_device *dev,
13981422
dst_cache_reset(&geneve->cfg.info.dst_cache);
13991423
memcpy(&geneve->cfg, cfg, sizeof(*cfg));
14001424

1425+
if (geneve->cfg.inner_proto_inherit) {
1426+
dev->header_ops = NULL;
1427+
dev->type = ARPHRD_NONE;
1428+
dev->hard_header_len = 0;
1429+
dev->addr_len = 0;
1430+
dev->flags = IFF_NOARP;
1431+
}
1432+
14011433
err = register_netdevice(dev);
14021434
if (err)
14031435
return err;
@@ -1571,10 +1603,18 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
15711603
#endif
15721604
}
15731605

1606+
if (data[IFLA_GENEVE_INNER_PROTO_INHERIT]) {
1607+
if (changelink) {
1608+
attrtype = IFLA_GENEVE_INNER_PROTO_INHERIT;
1609+
goto change_notsup;
1610+
}
1611+
cfg->inner_proto_inherit = true;
1612+
}
1613+
15741614
return 0;
15751615
change_notsup:
15761616
NL_SET_ERR_MSG_ATTR(extack, data[attrtype],
1577-
"Changing VNI, Port, endpoint IP address family, external, and UDP checksum attributes are not supported");
1617+
"Changing VNI, Port, endpoint IP address family, external, inner_proto_inherit, and UDP checksum attributes are not supported");
15781618
return -EOPNOTSUPP;
15791619
}
15801620

@@ -1809,6 +1849,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
18091849
if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit))
18101850
goto nla_put_failure;
18111851

1852+
if (geneve->cfg.inner_proto_inherit &&
1853+
nla_put_flag(skb, IFLA_GENEVE_INNER_PROTO_INHERIT))
1854+
goto nla_put_failure;
1855+
18121856
return 0;
18131857

18141858
nla_put_failure:

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ enum {
794794
IFLA_GENEVE_LABEL,
795795
IFLA_GENEVE_TTL_INHERIT,
796796
IFLA_GENEVE_DF,
797+
IFLA_GENEVE_INNER_PROTO_INHERIT,
797798
__IFLA_GENEVE_MAX
798799
};
799800
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)

0 commit comments

Comments
 (0)