aboutsummaryrefslogtreecommitdiffstats
path: root/net/mpls/af_mpls.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mpls/af_mpls.c')
-rw-r--r--net/mpls/af_mpls.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index c70d750148b6..c32fc411a911 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -27,6 +27,8 @@
27 */ 27 */
28#define MAX_MP_SELECT_LABELS 4 28#define MAX_MP_SELECT_LABELS 4
29 29
30#define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
31
30static int zero = 0; 32static int zero = 0;
31static int label_limit = (1 << 20) - 1; 33static int label_limit = (1 << 20) - 1;
32 34
@@ -317,7 +319,13 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
317 } 319 }
318 } 320 }
319 321
320 err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb); 322 /* If via wasn't specified then send out using device address */
323 if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC)
324 err = neigh_xmit(NEIGH_LINK_TABLE, out_dev,
325 out_dev->dev_addr, skb);
326 else
327 err = neigh_xmit(nh->nh_via_table, out_dev,
328 mpls_nh_via(rt, nh), skb);
321 if (err) 329 if (err)
322 net_dbg_ratelimited("%s: packet transmission failed: %d\n", 330 net_dbg_ratelimited("%s: packet transmission failed: %d\n",
323 __func__, err); 331 __func__, err);
@@ -534,6 +542,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
534 if (!mpls_dev_get(dev)) 542 if (!mpls_dev_get(dev))
535 goto errout; 543 goto errout;
536 544
545 if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
546 (dev->addr_len != nh->nh_via_alen))
547 goto errout;
548
537 RCU_INIT_POINTER(nh->nh_dev, dev); 549 RCU_INIT_POINTER(nh->nh_dev, dev);
538 550
539 return 0; 551 return 0;
@@ -592,10 +604,14 @@ static int mpls_nh_build(struct net *net, struct mpls_route *rt,
592 goto errout; 604 goto errout;
593 } 605 }
594 606
595 err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table, 607 if (via) {
596 __mpls_nh_via(rt, nh)); 608 err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
597 if (err) 609 __mpls_nh_via(rt, nh));
598 goto errout; 610 if (err)
611 goto errout;
612 } else {
613 nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
614 }
599 615
600 err = mpls_nh_assign_dev(net, rt, nh, oif); 616 err = mpls_nh_assign_dev(net, rt, nh, oif);
601 if (err) 617 if (err)
@@ -677,9 +693,6 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg,
677 nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST); 693 nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST);
678 } 694 }
679 695
680 if (!nla_via)
681 goto errout;
682
683 err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh, 696 err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh,
684 rtnh->rtnh_ifindex, nla_via, 697 rtnh->rtnh_ifindex, nla_via,
685 nla_newdst); 698 nla_newdst);
@@ -1118,6 +1131,7 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh,
1118 1131
1119 cfg->rc_label = LABEL_NOT_SPECIFIED; 1132 cfg->rc_label = LABEL_NOT_SPECIFIED;
1120 cfg->rc_protocol = rtm->rtm_protocol; 1133 cfg->rc_protocol = rtm->rtm_protocol;
1134 cfg->rc_via_table = MPLS_NEIGH_TABLE_UNSPEC;
1121 cfg->rc_nlflags = nlh->nlmsg_flags; 1135 cfg->rc_nlflags = nlh->nlmsg_flags;
1122 cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid; 1136 cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid;
1123 cfg->rc_nlinfo.nlh = nlh; 1137 cfg->rc_nlinfo.nlh = nlh;
@@ -1231,7 +1245,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
1231 nla_put_labels(skb, RTA_NEWDST, nh->nh_labels, 1245 nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
1232 nh->nh_label)) 1246 nh->nh_label))
1233 goto nla_put_failure; 1247 goto nla_put_failure;
1234 if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), 1248 if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
1249 nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
1235 nh->nh_via_alen)) 1250 nh->nh_via_alen))
1236 goto nla_put_failure; 1251 goto nla_put_failure;
1237 dev = rtnl_dereference(nh->nh_dev); 1252 dev = rtnl_dereference(nh->nh_dev);
@@ -1257,7 +1272,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
1257 nh->nh_labels, 1272 nh->nh_labels,
1258 nh->nh_label)) 1273 nh->nh_label))
1259 goto nla_put_failure; 1274 goto nla_put_failure;
1260 if (nla_put_via(skb, nh->nh_via_table, 1275 if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
1276 nla_put_via(skb, nh->nh_via_table,
1261 mpls_nh_via(rt, nh), 1277 mpls_nh_via(rt, nh),
1262 nh->nh_via_alen)) 1278 nh->nh_via_alen))
1263 goto nla_put_failure; 1279 goto nla_put_failure;
@@ -1319,7 +1335,8 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
1319 1335
1320 if (nh->nh_dev) 1336 if (nh->nh_dev)
1321 payload += nla_total_size(4); /* RTA_OIF */ 1337 payload += nla_total_size(4); /* RTA_OIF */
1322 payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */ 1338 if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */
1339 payload += nla_total_size(2 + nh->nh_via_alen);
1323 if (nh->nh_labels) /* RTA_NEWDST */ 1340 if (nh->nh_labels) /* RTA_NEWDST */
1324 payload += nla_total_size(nh->nh_labels * 4); 1341 payload += nla_total_size(nh->nh_labels * 4);
1325 } else { 1342 } else {
@@ -1328,7 +1345,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
1328 1345
1329 for_nexthops(rt) { 1346 for_nexthops(rt) {
1330 nhsize += nla_total_size(sizeof(struct rtnexthop)); 1347 nhsize += nla_total_size(sizeof(struct rtnexthop));
1331 nhsize += nla_total_size(2 + nh->nh_via_alen); 1348 /* RTA_VIA */
1349 if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC)
1350 nhsize += nla_total_size(2 + nh->nh_via_alen);
1332 if (nh->nh_labels) 1351 if (nh->nh_labels)
1333 nhsize += nla_total_size(nh->nh_labels * 4); 1352 nhsize += nla_total_size(nh->nh_labels * 4);
1334 } endfor_nexthops(rt); 1353 } endfor_nexthops(rt);