[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170816170202.456851-7-equinox@diac24.net>
Date: Wed, 16 Aug 2017 19:02:02 +0200
From: David Lamparter <equinox@...c24.net>
To: netdev@...r.kernel.org
Cc: amine.kherbouche@...nd.com, roopa@...ulusnetworks.com,
David Lamparter <equinox@...c24.net>
Subject: [PATCH 6/6] 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@...c24.net>
---
include/uapi/linux/rtnetlink.h | 4 ++++
net/mpls/af_mpls.c | 11 +++++++++++
net/mpls/internal.h | 8 ++------
net/mpls/vpls.c | 34 +++++++++++++++++++++++++++++++++-
4 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index b7840ed94526..b5a34e0e4327 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -327,6 +327,7 @@ enum rtattr_type_t {
RTA_UID,
RTA_TTL_PROPAGATE,
RTA_VPLS_IF,
+ RTA_VPLS_FLAGS,
__RTA_MAX
};
@@ -335,6 +336,9 @@ enum rtattr_type_t {
#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
+#define RTA_VPLS_F_CW_RX (1 << 0)
+#define RTA_VPLS_F_CW_TX (1 << 1)
+
/* RTM_MULTIPATH --- array of struct rtnexthop.
*
* "struct rtnexthop" describes all necessary nexthop information,
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 4d3ce007b7db..9036beeca173 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -477,6 +477,7 @@ struct mpls_route_config {
u32 rc_protocol;
u32 rc_ifindex;
u32 rc_vpls_ifindex;
+ u8 rc_vpls_flags;
u8 rc_via_table;
u8 rc_via_alen;
u8 rc_via[MAX_VIA_ALEN];
@@ -1036,6 +1037,7 @@ static int mpls_route_add(struct mpls_route_config *cfg,
rt->rt_payload_type = cfg->rc_payload_type;
rt->rt_ttl_propagate = cfg->rc_ttl_propagate;
rt->rt_vpls_dev = vpls_dev;
+ rt->rt_vpls_flags = cfg->rc_vpls_flags;
if (cfg->rc_mp)
err = mpls_nh_build_multi(cfg, rt, max_labels, extack);
@@ -1819,6 +1821,9 @@ static int rtm_to_route_config(struct sk_buff *skb,
cfg->rc_vpls_ifindex = nla_get_u32(nla);
cfg->rc_payload_type = MPT_VPLS;
break;
+ case RTA_VPLS_FLAGS:
+ cfg->rc_vpls_flags = nla_get_u8(nla);
+ break;
case RTA_NEWDST:
if (nla_get_labels(nla, MAX_NEW_LABELS,
&cfg->rc_output_labels,
@@ -1957,6 +1962,9 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
if (rt->rt_vpls_dev)
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
goto nla_put_failure;
+ if (rt->rt_vpls_flags)
+ if (nla_put_u8(skb, RTA_VPLS_FLAGS, rt->rt_vpls_flags))
+ goto nla_put_failure;
if (rt->rt_nhn == 1) {
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,
if (rt->rt_vpls_dev)
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
goto nla_put_failure;
+ if (rt->rt_vpls_flags)
+ if (nla_put_u8(skb, RTA_VPLS_FLAGS, rt->rt_vpls_flags))
+ goto nla_put_failure;
if (nh->nh_labels &&
nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
diff --git a/net/mpls/internal.h b/net/mpls/internal.h
index 876ae9993207..03048e3a5d83 100644
--- a/net/mpls/internal.h
+++ b/net/mpls/internal.h
@@ -79,11 +79,6 @@ enum mpls_payload_type {
MPT_VPLS = 2, /* pseudowire */
MPT_IPV4 = 4,
MPT_IPV6 = 6,
-
- /* Other types not implemented:
- * - Pseudo-wire with or without control word (RFC4385)
- * - GAL (RFC5586)
- */
};
struct mpls_nh { /* next hop label forwarding entry */
@@ -153,7 +148,8 @@ struct mpls_route { /* next hop label forwarding entry */
u8 rt_nhn_alive;
u8 rt_nh_size;
u8 rt_via_offset;
- u8 rt_reserved1;
+
+ u8 rt_vpls_flags;
struct net_device *rt_vpls_dev;
struct mpls_nh rt_nh[0];
diff --git a/net/mpls/vpls.c b/net/mpls/vpls.c
index 28ac810da6e9..1496683d871c 100644
--- a/net/mpls/vpls.c
+++ b/net/mpls/vpls.c
@@ -27,6 +27,14 @@
#define MIN_MTU 68 /* Min L3 MTU */
#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
+struct vpls_cw {
+ u8 type_flags;
+#define VPLS_CWTYPE(cw) ((cw)->type_flags & 0x0f)
+
+ u8 len;
+ u16 seqno;
+};
+
struct vpls_wirelist {
struct rcu_head rcu;
size_t count;
@@ -53,6 +61,14 @@ static int vpls_xmit_wire(struct sk_buff *skb, struct net_device *dev,
if (rt->rt_vpls_dev != dev)
return -EINVAL;
+ if (rt->rt_vpls_flags & RTA_VPLS_F_CW_TX) {
+ struct vpls_cw *cw;
+ if (skb_cow(skb, sizeof(*cw)))
+ return -ENOMEM;
+ cw = skb_push(skb, sizeof(*cw));
+ memset(cw, 0, sizeof(*cw));
+ }
+
return mpls_rt_xmit(skb, rt, dec);
}
@@ -123,6 +139,7 @@ int vpls_rcv(struct sk_buff *skb, struct net_device *in_dev,
struct mpls_entry_decoded dec;
struct metadata_dst *md_dst;
struct pcpu_sw_netstats *stats;
+ void *next;
if (!dev)
goto drop_nodev;
@@ -133,7 +150,22 @@ int vpls_rcv(struct sk_buff *skb, struct net_device *in_dev,
goto drop;
}
- skb_pull(skb, sizeof(*hdr));
+ /* bottom label is still in the skb */
+ next = skb_pull(skb, sizeof(*hdr));
+
+ if (rt->rt_vpls_flags & RTA_VPLS_F_CW_RX) {
+ struct vpls_cw *cw = next;
+ if (unlikely(!pskb_may_pull(skb, sizeof(*cw)))) {
+ dev->stats.rx_length_errors++;
+ goto drop;
+ }
+ next = skb_pull(skb, sizeof(*cw));
+
+ if (VPLS_CWTYPE(cw) != 0) {
+ /* insert MPLS OAM implementation here */
+ goto drop_nodev;
+ }
+ }
if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) {
dev->stats.rx_length_errors++;
--
2.13.0
Powered by blists - more mailing lists