Skip to content

Commit 0b29a8d

Browse files
committed
mpls: pseudowire control word support
[TODO: maybe rename this to MPLS_FLAGS and use it for non-pseudowire OAM bits too (e.g. enabling G-ACh or LSP ping.)] Signed-off-by: David Lamparter <equinox@diac24.net>
1 parent 0b2b0fe commit 0b29a8d

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

include/uapi/linux/rtnetlink.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ enum rtattr_type_t {
327327
RTA_UID,
328328
RTA_TTL_PROPAGATE,
329329
RTA_VPLS_IF,
330+
RTA_VPLS_FLAGS,
330331
__RTA_MAX
331332
};
332333

@@ -335,6 +336,9 @@ enum rtattr_type_t {
335336
#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
336337
#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
337338

339+
#define RTA_VPLS_F_CW_RX (1 << 0)
340+
#define RTA_VPLS_F_CW_TX (1 << 1)
341+
338342
/* RTM_MULTIPATH --- array of struct rtnexthop.
339343
*
340344
* "struct rtnexthop" describes all necessary nexthop information,

net/mpls/af_mpls.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ struct mpls_route_config {
477477
u32 rc_protocol;
478478
u32 rc_ifindex;
479479
u32 rc_vpls_ifindex;
480+
u8 rc_vpls_flags;
480481
u8 rc_via_table;
481482
u8 rc_via_alen;
482483
u8 rc_via[MAX_VIA_ALEN];
@@ -1036,6 +1037,7 @@ static int mpls_route_add(struct mpls_route_config *cfg,
10361037
rt->rt_payload_type = cfg->rc_payload_type;
10371038
rt->rt_ttl_propagate = cfg->rc_ttl_propagate;
10381039
rt->rt_vpls_dev = vpls_dev;
1040+
rt->rt_vpls_flags = cfg->rc_vpls_flags;
10391041

10401042
if (cfg->rc_mp)
10411043
err = mpls_nh_build_multi(cfg, rt, max_labels, extack);
@@ -1819,6 +1821,9 @@ static int rtm_to_route_config(struct sk_buff *skb,
18191821
cfg->rc_vpls_ifindex = nla_get_u32(nla);
18201822
cfg->rc_payload_type = MPT_VPLS;
18211823
break;
1824+
case RTA_VPLS_FLAGS:
1825+
cfg->rc_vpls_flags = nla_get_u8(nla);
1826+
break;
18221827
case RTA_NEWDST:
18231828
if (nla_get_labels(nla, MAX_NEW_LABELS,
18241829
&cfg->rc_output_labels,
@@ -1957,6 +1962,9 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
19571962
if (rt->rt_vpls_dev)
19581963
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
19591964
goto nla_put_failure;
1965+
if (rt->rt_vpls_flags)
1966+
if (nla_put_u8(skb, RTA_VPLS_FLAGS, rt->rt_vpls_flags))
1967+
goto nla_put_failure;
19601968

19611969
if (rt->rt_nhn == 1) {
19621970
const struct mpls_nh *nh = rt->rt_nh;
@@ -2270,6 +2278,9 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
22702278
if (rt->rt_vpls_dev)
22712279
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
22722280
goto nla_put_failure;
2281+
if (rt->rt_vpls_flags)
2282+
if (nla_put_u8(skb, RTA_VPLS_FLAGS, rt->rt_vpls_flags))
2283+
goto nla_put_failure;
22732284

22742285
if (nh->nh_labels &&
22752286
nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,

net/mpls/internal.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ enum mpls_payload_type {
7979
MPT_VPLS = 2, /* pseudowire */
8080
MPT_IPV4 = 4,
8181
MPT_IPV6 = 6,
82-
83-
/* Other types not implemented:
84-
* - Pseudo-wire with or without control word (RFC4385)
85-
* - GAL (RFC5586)
86-
*/
8782
};
8883

8984
struct mpls_nh { /* next hop label forwarding entry */
@@ -153,7 +148,8 @@ struct mpls_route { /* next hop label forwarding entry */
153148
u8 rt_nhn_alive;
154149
u8 rt_nh_size;
155150
u8 rt_via_offset;
156-
u8 rt_reserved1;
151+
152+
u8 rt_vpls_flags;
157153
struct net_device *rt_vpls_dev;
158154

159155
struct mpls_nh rt_nh[0];

net/mpls/vpls.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
#define MIN_MTU 68 /* Min L3 MTU */
2828
#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
2929

30+
struct vpls_cw {
31+
u8 type_flags;
32+
#define VPLS_CWTYPE(cw) ((cw)->type_flags & 0x0f)
33+
34+
u8 len;
35+
u16 seqno;
36+
};
37+
3038
struct vpls_wirelist {
3139
struct rcu_head rcu;
3240
size_t count;
@@ -53,6 +61,14 @@ static int vpls_xmit_wire(struct sk_buff *skb, struct net_device *dev,
5361
if (rt->rt_vpls_dev != dev)
5462
return -EINVAL;
5563

64+
if (rt->rt_vpls_flags & RTA_VPLS_F_CW_TX) {
65+
struct vpls_cw *cw;
66+
if (skb_cow(skb, sizeof(*cw)))
67+
return -ENOMEM;
68+
cw = skb_push(skb, sizeof(*cw));
69+
memset(cw, 0, sizeof(*cw));
70+
}
71+
5672
return mpls_rt_xmit(skb, rt, dec);
5773
}
5874

@@ -123,6 +139,7 @@ int vpls_rcv(struct sk_buff *skb, struct net_device *in_dev,
123139
struct mpls_entry_decoded dec;
124140
struct metadata_dst *md_dst;
125141
struct pcpu_sw_netstats *stats;
142+
void *next;
126143

127144
if (!dev)
128145
goto drop_nodev;
@@ -133,7 +150,22 @@ int vpls_rcv(struct sk_buff *skb, struct net_device *in_dev,
133150
goto drop;
134151
}
135152

136-
skb_pull(skb, sizeof(*hdr));
153+
/* bottom label is still in the skb */
154+
next = skb_pull(skb, sizeof(*hdr));
155+
156+
if (rt->rt_vpls_flags & RTA_VPLS_F_CW_RX) {
157+
struct vpls_cw *cw = next;
158+
if (unlikely(!pskb_may_pull(skb, sizeof(*cw)))) {
159+
dev->stats.rx_length_errors++;
160+
goto drop;
161+
}
162+
next = skb_pull(skb, sizeof(*cw));
163+
164+
if (VPLS_CWTYPE(cw) != 0) {
165+
/* insert MPLS OAM implementation here */
166+
goto drop_nodev;
167+
}
168+
}
137169

138170
if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) {
139171
dev->stats.rx_length_errors++;

0 commit comments

Comments
 (0)