Skip to content

Commit 4b5f672

Browse files
Martin Varghesedavem330
authored andcommitted
net: Special handling for IP & MPLS.
Special handling is needed in bareudp module for IP & MPLS as they support more than one ethertypes. MPLS has 2 ethertypes. 0x8847 for MPLS unicast and 0x8848 for MPLS multicast. While decapsulating MPLS packet from UDP packet the tunnel destination IP address is checked to determine the ethertype. The ethertype of the packet will be set to 0x8848 if the tunnel destination IP address is a multicast IP address. The ethertype of the packet will be set to 0x8847 if the tunnel destination IP address is a unicast IP address. IP has 2 ethertypes.0x0800 for IPV4 and 0x86dd for IPv6. The version field of the IP header tunnelled will be checked to determine the ethertype. This special handling to tunnel additional ethertypes will be disabled by default and can be enabled using a flag called multiproto. This flag can be used only with ethertypes 0x8847 and 0x0800. Signed-off-by: Martin Varghese <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 571912c commit 4b5f672

File tree

4 files changed

+85
-4
lines changed

4 files changed

+85
-4
lines changed

Documentation/networking/bareudp.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ The Bareudp tunnel module provides a generic L3 encapsulation tunnelling
1212
support for tunnelling different L3 protocols like MPLS, IP, NSH etc. inside
1313
a UDP tunnel.
1414

15+
Special Handling
16+
----------------
17+
The bareudp device supports special handling for MPLS & IP as they can have
18+
multiple ethertypes.
19+
MPLS procotcol can have ethertypes ETH_P_MPLS_UC (unicast) & ETH_P_MPLS_MC (multicast).
20+
IP protocol can have ethertypes ETH_P_IP (v4) & ETH_P_IPV6 (v6).
21+
This special handling can be enabled only for ethertypes ETH_P_IP & ETH_P_MPLS_UC
22+
with a flag called multiproto mode.
23+
1524
Usage
1625
------
1726

@@ -25,7 +34,16 @@ Usage
2534

2635
b) ip link delete bareudp0
2736

28-
2) Device Usage
37+
2) Device creation with multiple proto mode enabled
38+
39+
There are two ways to create a bareudp device for MPLS & IP with multiproto mode
40+
enabled.
41+
42+
a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype 0x8847 multiproto
43+
44+
b) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls
45+
46+
3) Device Usage
2947

3048
The bareudp device could be used along with OVS or flower filter in TC.
3149
The OVS or TC flower layer must set the tunnel information in SKB dst field before

drivers/net/bareudp.c

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct bareudp_dev {
4545
__be16 ethertype;
4646
__be16 port;
4747
u16 sport_min;
48+
bool multi_proto_mode;
4849
struct socket __rcu *sock;
4950
struct list_head next; /* bareudp node on namespace list */
5051
struct gro_cells gro_cells;
@@ -70,7 +71,52 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
7071
else
7172
family = AF_INET6;
7273

73-
proto = bareudp->ethertype;
74+
if (bareudp->ethertype == htons(ETH_P_IP)) {
75+
struct iphdr *iphdr;
76+
77+
iphdr = (struct iphdr *)(skb->data + BAREUDP_BASE_HLEN);
78+
if (iphdr->version == 4) {
79+
proto = bareudp->ethertype;
80+
} else if (bareudp->multi_proto_mode && (iphdr->version == 6)) {
81+
proto = htons(ETH_P_IPV6);
82+
} else {
83+
bareudp->dev->stats.rx_dropped++;
84+
goto drop;
85+
}
86+
} else if (bareudp->ethertype == htons(ETH_P_MPLS_UC)) {
87+
struct iphdr *tunnel_hdr;
88+
89+
tunnel_hdr = (struct iphdr *)skb_network_header(skb);
90+
if (tunnel_hdr->version == 4) {
91+
if (!ipv4_is_multicast(tunnel_hdr->daddr)) {
92+
proto = bareudp->ethertype;
93+
} else if (bareudp->multi_proto_mode &&
94+
ipv4_is_multicast(tunnel_hdr->daddr)) {
95+
proto = htons(ETH_P_MPLS_MC);
96+
} else {
97+
bareudp->dev->stats.rx_dropped++;
98+
goto drop;
99+
}
100+
} else {
101+
int addr_type;
102+
struct ipv6hdr *tunnel_hdr_v6;
103+
104+
tunnel_hdr_v6 = (struct ipv6hdr *)skb_network_header(skb);
105+
addr_type =
106+
ipv6_addr_type((struct in6_addr *)&tunnel_hdr_v6->daddr);
107+
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
108+
proto = bareudp->ethertype;
109+
} else if (bareudp->multi_proto_mode &&
110+
(addr_type & IPV6_ADDR_MULTICAST)) {
111+
proto = htons(ETH_P_MPLS_MC);
112+
} else {
113+
bareudp->dev->stats.rx_dropped++;
114+
goto drop;
115+
}
116+
}
117+
} else {
118+
proto = bareudp->ethertype;
119+
}
74120

75121
if (iptunnel_pull_header(skb, BAREUDP_BASE_HLEN,
76122
proto,
@@ -369,8 +415,12 @@ static netdev_tx_t bareudp_xmit(struct sk_buff *skb, struct net_device *dev)
369415
int err;
370416

371417
if (skb->protocol != bareudp->ethertype) {
372-
err = -EINVAL;
373-
goto tx_error;
418+
if (!bareudp->multi_proto_mode ||
419+
(skb->protocol != htons(ETH_P_MPLS_MC) &&
420+
skb->protocol != htons(ETH_P_IPV6))) {
421+
err = -EINVAL;
422+
goto tx_error;
423+
}
374424
}
375425

376426
info = skb_tunnel_info(skb);
@@ -463,6 +513,7 @@ static const struct nla_policy bareudp_policy[IFLA_BAREUDP_MAX + 1] = {
463513
[IFLA_BAREUDP_PORT] = { .type = NLA_U16 },
464514
[IFLA_BAREUDP_ETHERTYPE] = { .type = NLA_U16 },
465515
[IFLA_BAREUDP_SRCPORT_MIN] = { .type = NLA_U16 },
516+
[IFLA_BAREUDP_MULTIPROTO_MODE] = { .type = NLA_FLAG },
466517
};
467518

468519
/* Info for udev, that this is a virtual tunnel endpoint */
@@ -545,9 +596,15 @@ static int bareudp_configure(struct net *net, struct net_device *dev,
545596
if (t)
546597
return -EBUSY;
547598

599+
if (conf->multi_proto_mode &&
600+
(conf->ethertype != htons(ETH_P_MPLS_UC) &&
601+
conf->ethertype != htons(ETH_P_IP)))
602+
return -EINVAL;
603+
548604
bareudp->port = conf->port;
549605
bareudp->ethertype = conf->ethertype;
550606
bareudp->sport_min = conf->sport_min;
607+
bareudp->multi_proto_mode = conf->multi_proto_mode;
551608
err = register_netdevice(dev);
552609
if (err)
553610
return err;
@@ -604,6 +661,7 @@ static size_t bareudp_get_size(const struct net_device *dev)
604661
return nla_total_size(sizeof(__be16)) + /* IFLA_BAREUDP_PORT */
605662
nla_total_size(sizeof(__be16)) + /* IFLA_BAREUDP_ETHERTYPE */
606663
nla_total_size(sizeof(__u16)) + /* IFLA_BAREUDP_SRCPORT_MIN */
664+
nla_total_size(0) + /* IFLA_BAREUDP_MULTIPROTO_MODE */
607665
0;
608666
}
609667

@@ -617,6 +675,9 @@ static int bareudp_fill_info(struct sk_buff *skb, const struct net_device *dev)
617675
goto nla_put_failure;
618676
if (nla_put_u16(skb, IFLA_BAREUDP_SRCPORT_MIN, bareudp->sport_min))
619677
goto nla_put_failure;
678+
if (bareudp->multi_proto_mode &&
679+
nla_put_flag(skb, IFLA_BAREUDP_MULTIPROTO_MODE))
680+
goto nla_put_failure;
620681

621682
return 0;
622683

include/net/bareudp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct bareudp_conf {
1010
__be16 ethertype;
1111
__be16 port;
1212
u16 sport_min;
13+
bool multi_proto_mode;
1314
};
1415

1516
struct net_device *bareudp_dev_create(struct net *net, const char *name,

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ enum {
596596
IFLA_BAREUDP_PORT,
597597
IFLA_BAREUDP_ETHERTYPE,
598598
IFLA_BAREUDP_SRCPORT_MIN,
599+
IFLA_BAREUDP_MULTIPROTO_MODE,
599600
__IFLA_BAREUDP_MAX
600601
};
601602

0 commit comments

Comments
 (0)