Skip to content

Commit 72a2adf

Browse files
committed
mpls: add VPLS entry points
This wires up the neccessary calls for VPLS into the MPLS forwarding pieces. Since CONFIG_MPLS_VPLS doesn't exist yet in Kconfig, it'll never be enabled, so we're on the stubs for now. Signed-off-by: David Lamparter <equinox@diac24.net>
1 parent 7f45c29 commit 72a2adf

3 files changed

Lines changed: 84 additions & 0 deletions

File tree

include/uapi/linux/rtnetlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ enum rtattr_type_t {
326326
RTA_PAD,
327327
RTA_UID,
328328
RTA_TTL_PROPAGATE,
329+
RTA_VPLS_IF,
329330
__RTA_MAX
330331
};
331332

net/mpls/af_mpls.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,11 @@ static bool mpls_egress(struct net *net, struct mpls_route *rt,
299299
success = true;
300300
break;
301301
}
302+
case MPT_VPLS:
303+
/* nothing to do here, no TTL in Ethernet
304+
* (and we shouldn't mess with the TTL in inner IP packets,
305+
* pseudowires are supposed to be transparent) */
306+
break;
302307
case MPT_UNSPEC:
303308
/* Should have decided which protocol it is by now */
304309
break;
@@ -349,6 +354,8 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
349354
goto drop;
350355
}
351356

357+
if (rt->rt_payload_type == MPT_VPLS)
358+
return vpls_rcv(skb, dev, pt, rt, hdr, orig_dev);
352359

353360
/* Pop the label */
354361
skb_pull(skb, sizeof(*hdr));
@@ -469,6 +476,7 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = {
469476
struct mpls_route_config {
470477
u32 rc_protocol;
471478
u32 rc_ifindex;
479+
u32 rc_vpls_ifindex;
472480
u8 rc_via_table;
473481
u8 rc_via_alen;
474482
u8 rc_via[MAX_VIA_ALEN];
@@ -541,6 +549,8 @@ static void mpls_route_update(struct net *net, unsigned index,
541549
rt = rtnl_dereference(platform_label[index]);
542550
rcu_assign_pointer(platform_label[index], new);
543551

552+
vpls_label_update(index, rt, new);
553+
544554
mpls_notify_route(net, index, rt, new, info);
545555

546556
/* If we removed a route free it now */
@@ -942,6 +952,7 @@ static int mpls_route_add(struct mpls_route_config *cfg,
942952
struct mpls_route __rcu **platform_label;
943953
struct net *net = cfg->rc_nlinfo.nl_net;
944954
struct mpls_route *rt, *old;
955+
struct net_device *vpls_dev = NULL;
945956
int err = -EINVAL;
946957
u8 max_via_alen;
947958
unsigned index;
@@ -996,6 +1007,24 @@ static int mpls_route_add(struct mpls_route_config *cfg,
9961007
goto errout;
9971008
}
9981009

1010+
if (cfg->rc_vpls_ifindex) {
1011+
vpls_dev = dev_get_by_index(net, cfg->rc_vpls_ifindex);
1012+
if (!vpls_dev) {
1013+
err = -ENODEV;
1014+
NL_SET_ERR_MSG(extack, "Invalid VPLS ifindex");
1015+
goto errout;
1016+
}
1017+
/* we're under RTNL; and we'll drop routes when we're
1018+
* notified the device is going away. */
1019+
dev_put(vpls_dev);
1020+
1021+
if (!is_vpls_dev(vpls_dev)) {
1022+
err = -ENODEV;
1023+
NL_SET_ERR_MSG(extack, "Not a VPLS device");
1024+
goto errout;
1025+
}
1026+
}
1027+
9991028
err = -ENOMEM;
10001029
rt = mpls_rt_alloc(nhs, max_via_alen, max_labels);
10011030
if (IS_ERR(rt)) {
@@ -1006,6 +1035,7 @@ static int mpls_route_add(struct mpls_route_config *cfg,
10061035
rt->rt_protocol = cfg->rc_protocol;
10071036
rt->rt_payload_type = cfg->rc_payload_type;
10081037
rt->rt_ttl_propagate = cfg->rc_ttl_propagate;
1038+
rt->rt_vpls_dev = vpls_dev;
10091039

10101040
if (cfg->rc_mp)
10111041
err = mpls_nh_build_multi(cfg, rt, max_labels, extack);
@@ -1430,6 +1460,14 @@ static void mpls_ifdown(struct net_device *dev, int event)
14301460
if (!rt)
14311461
continue;
14321462

1463+
if (rt->rt_vpls_dev == dev) {
1464+
switch (event) {
1465+
case NETDEV_UNREGISTER:
1466+
mpls_route_update(net, index, NULL, NULL);
1467+
continue;
1468+
}
1469+
}
1470+
14331471
alive = 0;
14341472
deleted = 0;
14351473
change_nexthops(rt) {
@@ -1777,6 +1815,10 @@ static int rtm_to_route_config(struct sk_buff *skb,
17771815
case RTA_OIF:
17781816
cfg->rc_ifindex = nla_get_u32(nla);
17791817
break;
1818+
case RTA_VPLS_IF:
1819+
cfg->rc_vpls_ifindex = nla_get_u32(nla);
1820+
cfg->rc_payload_type = MPT_VPLS;
1821+
break;
17801822
case RTA_NEWDST:
17811823
if (nla_get_labels(nla, MAX_NEW_LABELS,
17821824
&cfg->rc_output_labels,
@@ -1911,6 +1953,11 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
19111953
ttl_propagate))
19121954
goto nla_put_failure;
19131955
}
1956+
1957+
if (rt->rt_vpls_dev)
1958+
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
1959+
goto nla_put_failure;
1960+
19141961
if (rt->rt_nhn == 1) {
19151962
const struct mpls_nh *nh = rt->rt_nh;
19161963

@@ -2220,6 +2267,10 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
22202267
if (nla_put_labels(skb, RTA_DST, 1, &in_label))
22212268
goto nla_put_failure;
22222269

2270+
if (rt->rt_vpls_dev)
2271+
if (nla_put_u32(skb, RTA_VPLS_IF, rt->rt_vpls_dev->ifindex))
2272+
goto nla_put_failure;
2273+
22232274
if (nh->nh_labels &&
22242275
nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
22252276
nh->nh_label))
@@ -2491,6 +2542,8 @@ static int __init mpls_init(void)
24912542

24922543
rtnl_af_register(&mpls_af_ops);
24932544

2545+
vpls_init();
2546+
24942547
rtnl_register(PF_MPLS, RTM_NEWROUTE, mpls_rtm_newroute, NULL, 0);
24952548
rtnl_register(PF_MPLS, RTM_DELROUTE, mpls_rtm_delroute, NULL, 0);
24962549
rtnl_register(PF_MPLS, RTM_GETROUTE, mpls_getroute, mpls_dump_routes,
@@ -2510,6 +2563,7 @@ module_init(mpls_init);
25102563
static void __exit mpls_exit(void)
25112564
{
25122565
rtnl_unregister_all(PF_MPLS);
2566+
vpls_exit();
25132567
rtnl_af_unregister(&mpls_af_ops);
25142568
dev_remove_pack(&mpls_packet_type);
25152569
unregister_netdevice_notifier(&mpls_dev_notifier);

net/mpls/internal.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct sk_buff;
7676

7777
enum mpls_payload_type {
7878
MPT_UNSPEC, /* IPv4 or IPv6 */
79+
MPT_VPLS = 2, /* pseudowire */
7980
MPT_IPV4 = 4,
8081
MPT_IPV6 = 6,
8182

@@ -153,6 +154,8 @@ struct mpls_route { /* next hop label forwarding entry */
153154
u8 rt_nh_size;
154155
u8 rt_via_offset;
155156
u8 rt_reserved1;
157+
struct net_device *rt_vpls_dev;
158+
156159
struct mpls_nh rt_nh[0];
157160
};
158161

@@ -214,4 +217,30 @@ struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index);
214217
int mpls_rt_xmit(struct sk_buff *skb, struct mpls_route *rt,
215218
struct mpls_entry_decoded dec);
216219

220+
#ifdef CONFIG_MPLS_VPLS
221+
int vpls_rcv(struct sk_buff *skb, struct net_device *in_dev,
222+
struct packet_type *pt, struct mpls_route *rt,
223+
struct mpls_shim_hdr *hdr, struct net_device *orig_dev);
224+
void vpls_label_update(unsigned label, struct mpls_route *rt_old,
225+
struct mpls_route *rt_new);
226+
__init int vpls_init(void);
227+
__exit void vpls_exit(void);
228+
int is_vpls_dev(struct net_device *dev);
229+
230+
#else /* !CONFIG_MPLS_VPLS */
231+
static inline int vpls_rcv(skb, in_dev, pt, rt, hdr, orig_dev)
232+
{
233+
kfree_skb(skb);
234+
return NET_RX_DROP;
235+
}
236+
static inline int is_vpls_dev(struct net_device *dev)
237+
{
238+
return 0;
239+
}
240+
241+
#define vpls_label_update(label, rt_old, rt_new) do { } while (0)
242+
#define vpls_init() do { } while (0)
243+
#define vpls_exit() do { } while (0)
244+
#endif
245+
217246
#endif /* MPLS_INTERNAL_H */

0 commit comments

Comments
 (0)