Revision d14f8c3c

View differences:

conf/confbase.Y
270 270

  
271 271
label_stack_start: NUM
272 272
{
273
  $$ = cfg_allocz(sizeof(u32) * (NEXTHOP_MAX_LABEL_STACK+1));
273
  $$ = cfg_allocz(sizeof(u32) * (MPLS_MAX_LABEL_STACK+1));
274 274
  $$[0] = 1;
275 275
  $$[1] = $1;
276 276
};
......
278 278
label_stack:
279 279
    label_stack_start
280 280
  | label_stack '/' NUM {
281
    if ($1[0] >= NEXTHOP_MAX_LABEL_STACK)
281
    if ($1[0] >= MPLS_MAX_LABEL_STACK)
282 282
      cf_error("Too many labels in stack.");
283 283
    $1[++$1[0]] = $3;
284 284
    $$ = $1;
lib/ip.h
325 325
static inline ip6_addr ip6_ntoh(ip6_addr a)
326 326
{ return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
327 327

  
328
#define MPLS_MAX_LABEL_STACK 8
329
static inline int
330
mpls_get(const char *buf, int buflen, u32 *stack)
331
{
332
  for (int i=0; (i<MPLS_MAX_LABEL_STACK) && (i*4+3 < buflen); i++)
333
  {
334
    u32 s = get_u32(buf + i*4);
335
    stack[i] = s >> 12;
336
    if (s & 0x100)
337
      return i+1;
338
  }
339
  return -1;
340
}
341

  
342
static inline int
343
mpls_put(char *buf, int len, u32 *stack)
344
{
345
  for (int i=0; i<len; i++)
346
    put_u32(buf + i*4, stack[i] << 12 | (i+1 == len ? 0x100 : 0));
347

  
348
  return len*4;
349
}
328 350

  
329 351
/*
330 352
 *	Unaligned data access (in network order)
lib/net.c
225 225
  case NET_FLOW6:
226 226
    return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
227 227

  
228
  /* classify probably not needed for NET_MPLS */
228
  case NET_MPLS:
229
    return IADDR_HOST | SCOPE_UNIVERSE;
229 230
  }
230 231

  
231 232
  return IADDR_INVALID;
lib/net.h
259 259
  }
260 260
}
261 261

  
262
static inline u32 net_mpls(const net_addr *a)
263
{
264
  if (a->type == NET_MPLS)
265
    return ((net_addr_mpls *) a)->label;
266

  
267
  bug("Can't call net_mpls on non-mpls net_addr");
268
}
269

  
262 270
static inline uint net4_pxlen(const net_addr *a)
263 271
{ return a->pxlen; }
264 272

  
nest/route.h
512 512
ea_list *ea_append(ea_list *to, ea_list *what);
513 513
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
514 514

  
515
#define NEXTHOP_MAX_LABEL_STACK 8
516
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK)
515
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
517 516

  
518 517
static inline size_t nexthop_size(const struct nexthop *nh)
519 518
{ return sizeof(struct nexthop) + sizeof(u32)*nh->labels; }
......
528 527

  
529 528
void rta_init(void);
530 529
static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; }
531
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK)
530
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
532 531
rta *rta_lookup(rta *);			/* Get rta equivalent to this one, uc++ */
533 532
static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; }
534 533
static inline rta *rta_clone(rta *r) { r->uc++; return r; }
nest/rt-attr.c
1279 1279
  rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
1280 1280
  rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));
1281 1281
  rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2);
1282
  rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
1282
  rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
1283 1283

  
1284 1284
  nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop));
1285 1285
  nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32));
1286 1286
  nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
1287
  nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
1287
  nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
1288 1288

  
1289 1289
  rta_alloc_hash();
1290 1290
  rte_src_init();
nest/rt-table.c
2487 2487
	     tm, from, primary ? (sync_error ? " !" : " *") : "", info);
2488 2488
  for (nh = &(a->nh); nh; nh = nh->next)
2489 2489
    {
2490
      char ls[NEXTHOP_MAX_LABEL_STACK*8 + 5]; char *lsp = ls;
2490
      char ls[MPLS_MAX_LABEL_STACK*8 + 5]; char *lsp = ls;
2491 2491
      if (nh->labels)
2492 2492
	{
2493 2493
	  lsp += bsprintf(lsp, " mpls %d", nh->label[0]);
sysdep/cf/linux.h
21 21
#define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h"
22 22

  
23 23

  
24
#ifndef AF_MPLS
25
#define AF_MPLS 28
26
#endif
27

  
24 28
/*
25 29
Link: sysdep/linux
26 30
Link: sysdep/unix
sysdep/linux/netlink.c
31 31

  
32 32
#include <asm/types.h>
33 33
#include <linux/if.h>
34
#include <linux/lwtunnel.h>
34 35
#include <linux/netlink.h>
35 36
#include <linux/rtnetlink.h>
36 37

  
......
51 52
#define RTA_TABLE  15
52 53
#endif
53 54

  
55
#ifndef RTA_VIA
56
#define RTA_VIA	 18
57
#endif
58

  
59
#ifndef RTA_NEWDST
60
#define RTA_NEWDST  19
61
#endif
62

  
63
#ifndef RTA_ENCAP_TYPE
64
#define RTA_ENCAP_TYPE	21
65
#endif
66

  
67
#ifndef RTA_ENCAP
68
#define RTA_ENCAP  22
69
#endif
54 70

  
55 71
#define krt_ecmp6(p) ((p)->af == AF_INET6)
56 72

  
......
313 329
};
314 330

  
315 331

  
316
#define BIRD_RTA_MAX  (RTA_TABLE+1)
332
#define BIRD_RTA_MAX  (RTA_ENCAP+1)
317 333

  
318 334
static struct nl_want_attrs nexthop_attr_want4[BIRD_RTA_MAX] = {
319 335
  [RTA_GATEWAY]	  = { 1, 1, sizeof(ip4_addr) },
336
  [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
337
  [RTA_ENCAP]	  = { 1, 0, 0 },
338
};
339

  
340
static struct nl_want_attrs encap_mpls_want[BIRD_RTA_MAX] = {
341
  [RTA_DST]       = { 1, 0, 0 },
320 342
};
321 343

  
322 344
static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = {
......
329 351
  [RTA_MULTIPATH] = { 1, 0, 0 },
330 352
  [RTA_FLOW]	  = { 1, 1, sizeof(u32) },
331 353
  [RTA_TABLE]	  = { 1, 1, sizeof(u32) },
354
  [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
355
  [RTA_ENCAP]	  = { 1, 0, 0 },
332 356
};
333 357

  
334 358
static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = {
......
341 365
  [RTA_METRICS]	  = { 1, 0, 0 },
342 366
  [RTA_FLOW]	  = { 1, 1, sizeof(u32) },
343 367
  [RTA_TABLE]	  = { 1, 1, sizeof(u32) },
368
  [RTA_ENCAP_TYPE]= { 1, 1, sizeof(u16) },
369
  [RTA_ENCAP]	  = { 1, 0, 0 },
370
};
371

  
372
static struct nl_want_attrs rtm_attr_want_mpls[BIRD_RTA_MAX] = {
373
  [RTA_DST]	  = { 1, 1, sizeof(u32) },
374
  [RTA_IIF]	  = { 1, 1, sizeof(u32) },
375
  [RTA_OIF]	  = { 1, 1, sizeof(u32) },
376
  [RTA_PRIORITY]  = { 1, 1, sizeof(u32) },
377
  [RTA_METRICS]	  = { 1, 0, 0 },
378
  [RTA_FLOW]	  = { 1, 1, sizeof(u32) },
379
  [RTA_TABLE]	  = { 1, 1, sizeof(u32) },
380
  [RTA_VIA]	  = { 1, 0, 0 },
381
  [RTA_NEWDST]	  = { 1, 0, 0 },
344 382
};
345 383

  
346 384

  
......
373 411
  return 1;
374 412
}
375 413

  
414
static inline u16 rta_get_u16(struct rtattr *a)
415
{ return *(u16 *) RTA_DATA(a); }
416

  
376 417
static inline u32 rta_get_u32(struct rtattr *a)
377 418
{ return *(u32 *) RTA_DATA(a); }
378 419

  
......
390 431
    return ipa_from_ip6(rta_get_ip6(a));
391 432
}
392 433

  
434
static inline ip_addr rta_get_via(struct rtattr *a)
435
{
436
  struct rtvia *v = RTA_DATA(a);
437
  switch(v->rtvia_family) {
438
    case AF_INET:  return ipa_from_ip4(ip4_ntoh(*(ip4_addr *) v->rtvia_addr));
439
    case AF_INET6: return ipa_from_ip6(ip6_ntoh(*(ip6_addr *) v->rtvia_addr));
440
  }
441
  return IPA_NONE;
442
}
443

  
444
static u32 rta_mpls_stack[MPLS_MAX_LABEL_STACK];
445
static inline int rta_get_mpls(struct rtattr *a, u32 *stack)
446
{
447
  if (RTA_PAYLOAD(a) % 4)
448
    log(L_WARN "KRT: Strange length of received MPLS stack: %u", RTA_PAYLOAD(a));
449

  
450
  return mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack);
451
}
452

  
393 453
struct rtattr *
394 454
nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint dlen)
395 455
{
......
410 470
  return a;
411 471
}
412 472

  
473
static inline struct rtattr *
474
nl_open_attr(struct nlmsghdr *h, uint bufsize, uint code)
475
{
476
  return nl_add_attr(h, bufsize, code, NULL, 0);
477
}
478

  
479
static inline void
480
nl_close_attr(struct nlmsghdr *h, struct rtattr *a)
481
{
482
  a->rta_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)a;
483
}
484

  
485
static inline void
486
nl_add_attr_u16(struct nlmsghdr *h, uint bufsize, int code, u16 data)
487
{
488
  nl_add_attr(h, bufsize, code, &data, 2);
489
}
490

  
413 491
static inline void
414 492
nl_add_attr_u32(struct nlmsghdr *h, uint bufsize, int code, u32 data)
415 493
{
......
439 517
    nl_add_attr_ip6(h, bufsize, code, ipa_to_ip6(ipa));
440 518
}
441 519

  
442
static inline struct rtattr *
443
nl_open_attr(struct nlmsghdr *h, uint bufsize, uint code)
520
static inline void
521
nl_add_attr_mpls(struct nlmsghdr *h, uint bufsize, int code, int len, u32 *stack)
444 522
{
445
  return nl_add_attr(h, bufsize, code, NULL, 0);
523
  char buf[len*4];
524
  mpls_put(buf, len, stack);
525
  nl_add_attr(h, bufsize, code, buf, len*4);
446 526
}
447 527

  
448 528
static inline void
449
nl_close_attr(struct nlmsghdr *h, struct rtattr *a)
529
nl_add_attr_mpls_encap(struct nlmsghdr *h, uint bufsize, int len, u32 *stack)
450 530
{
451
  a->rta_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)a;
531
  nl_add_attr_u16(h, bufsize, RTA_ENCAP_TYPE, LWTUNNEL_ENCAP_MPLS);
532

  
533
  struct rtattr *nest = nl_open_attr(h, bufsize, RTA_ENCAP);
534
  nl_add_attr_mpls(h, bufsize, RTA_DST, len, stack);
535
  nl_close_attr(h, nest);
536
}
537

  
538
static inline void
539
nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa)
540
{
541
  struct rtattr *nest = nl_open_attr(h, bufsize, RTA_VIA);
542
  struct rtvia *via = RTA_DATA(nest);
543

  
544
  h->nlmsg_len += sizeof(*via);
545

  
546
  if (ipa_is_ip4(ipa)) {
547
    ip4_addr ip4 = ipa_to_ip4(ipa);
548
    ip4 = ip4_hton(ip4);
549
    via->rtvia_family = AF_INET;
550
    memcpy(via->rtvia_addr, &ip4, sizeof(ip4));
551
    h->nlmsg_len += sizeof(ip4);
552
  } else {
553
    ip6_addr ip6 = ipa_to_ip6(ipa);
554
    ip6 = ip6_hton(ip6);
555
    via->rtvia_family = AF_INET6;
556
    memcpy(via->rtvia_addr, &ip6, sizeof(ip6));
557
    h->nlmsg_len += sizeof(ip6);
558
  }
559

  
560
  nl_close_attr(h, nest);
452 561
}
453 562

  
454 563
static inline struct rtnexthop *
......
471 580
  nh->rtnh_len = (void *)h + NLMSG_ALIGN(h->nlmsg_len) - (void *)nh;
472 581
}
473 582

  
583
static inline void
584
nl_add_nexthop(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af)
585
{
586
  if (nh->labels > 0)
587
    if (af == AF_MPLS)
588
      nl_add_attr_mpls(h, bufsize, RTA_NEWDST, nh->labels, nh->label);
589
    else
590
      nl_add_attr_mpls_encap(h, bufsize, nh->labels, nh->label);
591

  
592
  if (ipa_nonzero(nh->gw))
593
    if (af == AF_MPLS)
594
      nl_add_attr_via(h, bufsize, nh->gw);
595
    else
596
      nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw);
597
}
598

  
474 599
static void
475
nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh)
600
nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af)
476 601
{
477 602
  struct rtattr *a = nl_open_attr(h, bufsize, RTA_MULTIPATH);
478 603

  
......
484 609
    rtnh->rtnh_hops = nh->weight;
485 610
    rtnh->rtnh_ifindex = nh->iface->index;
486 611

  
487
    nl_add_attr_ipa(h, bufsize, RTA_GATEWAY, nh->gw);
612
    nl_add_nexthop(h, bufsize, nh, af);
488 613

  
489 614
    nl_close_nexthop(h, rtnh);
490 615
  }
......
518 643
      if (nh_buf_used == nh_buf_size)
519 644
      {
520 645
	nh_buf_size = nh_buf_size ? (nh_buf_size * 2) : 4;
521
	nh_buffer = xrealloc(nh_buffer, nh_buf_size * sizeof(struct nexthop));
646
	nh_buffer = xrealloc(nh_buffer, nh_buf_size * NEXTHOP_MAX_SIZE);
522 647
      }
523 648
      *last = rv = nh_buffer + nh_buf_used++;
524 649
      rv->next = NULL;
......
543 668
	    return NULL;
544 669
	}
545 670
      else
546
	return NULL;
671
	rv->gw = IPA_NONE;
672
      if (a[RTA_ENCAP_TYPE])
673
	{
674
	  if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
675
	    log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE]));
676
	    return NULL;
677
	  }
678

  
679
	  struct rtattr *enca[BIRD_RTA_MAX];
680
	  nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
681
	  nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
682
	  rv->labels = rta_get_mpls(enca[RTA_DST], rv->label);
683
	  break;
684
	}
685

  
547 686

  
548 687
      len -= NLMSG_ALIGN(nh->rtnh_len);
549 688
      nh = RTNH_NEXT(nh);
......
1008 1147
  r->r.rtm_dst_len = net_pxlen(net->n.addr);
1009 1148
  r->r.rtm_protocol = RTPROT_BIRD;
1010 1149
  r->r.rtm_scope = RT_SCOPE_UNIVERSE;
1011
  nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
1150
  if (p->af == AF_MPLS)
1151
  {
1152
    u32 label = net_mpls(net->n.addr);
1153
    nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
1154
  }
1155
  else
1156
    nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
1012 1157

  
1013 1158
  /*
1014 1159
   * Strange behavior for RTM_DELROUTE:
......
1071 1216
    case RTD_UNICAST:
1072 1217
      r->r.rtm_type = RTN_UNICAST;
1073 1218
      if (nh->next && !krt_ecmp6(p))
1074
	nl_add_multipath(&r->h, rsize, nh);
1219
	nl_add_multipath(&r->h, rsize, nh, p->af);
1075 1220
      else
1076 1221
      {
1077 1222
	nl_add_attr_u32(&r->h, rsize, RTA_OIF, nh->iface->index);
1078

  
1079
	if (ipa_nonzero(nh->gw))
1080
	  nl_add_attr_ipa(&r->h, rsize, RTA_GATEWAY, nh->gw);
1223
	nl_add_nexthop(&r->h, rsize, nh, p->af);
1081 1224
      }
1082 1225
      break;
1083 1226
    case RTD_BLACKHOLE:
......
1276 1419
	net_fill_ip6(&dst, IP6_NONE, 0);
1277 1420
      break;
1278 1421

  
1422
    case AF_MPLS:
1423
      if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want_mpls, a, sizeof(a)))
1424
	return;
1425

  
1426
      if (a[RTA_DST])
1427
	if (rta_get_mpls(a[RTA_DST], rta_mpls_stack) == 1)
1428
	  net_fill_mpls(&dst, rta_mpls_stack[0]);
1429
	else
1430
	  log(L_WARN "KRT: Got multi-label MPLS RTA_DST");
1431
      else
1432
	return; /* No support for MPLS routes without RTA_DST */
1433
      break;
1434

  
1279 1435
    default:
1280 1436
      return;
1281 1437
    }
......
1338 1494
  if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type))
1339 1495
    nl_announce_route(s);
1340 1496

  
1341
  rta *ra = lp_allocz(s->pool, sizeof(rta)); // TODO: fix alloc
1497
  rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
1342 1498
  ra->src = p->p.main_source;
1343 1499
  ra->source = RTS_INHERIT;
1344 1500
  ra->scope = SCOPE_UNIVERSE;
......
1367 1523
	  return;
1368 1524
	}
1369 1525

  
1370
      if (a[RTA_GATEWAY])
1526
      if ((i->rtm_family != AF_MPLS) && a[RTA_GATEWAY] || (i->rtm_family == AF_MPLS) && a[RTA_VIA])
1371 1527
	{
1372
	  ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]);
1528
	  if (i->rtm_family == AF_MPLS)
1529
	    ra->nh.gw = rta_get_via(a[RTA_VIA]);
1530
	  else
1531
	    ra->nh.gw = rta_get_ipa(a[RTA_GATEWAY]);
1373 1532

  
1374 1533
	  /* Silently skip strange 6to4 routes */
1375 1534
	  const net_addr_ip6 sit = NET_ADDR_IP6(IP6_NONE, 96);
......
1377 1536
	    return;
1378 1537

  
1379 1538
	  neighbor *nbr;
1380
	  nbr = neigh_find2(&p->p, &ra->nh.gw, ra->nh.iface,
1539
	  nbr = neigh_find2(&p->p, &(ra->nh.gw), ra->nh.iface,
1381 1540
			    (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
1382 1541
	  if (!nbr || (nbr->scope == SCOPE_HOST))
1383 1542
	    {
......
1403 1562
      return;
1404 1563
    }
1405 1564

  
1565
  int labels = 0;
1566
  if ((i->rtm_family == AF_MPLS) && a[RTA_NEWDST] && !ra->nh.next)
1567
    labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label);
1568

  
1569
  if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE] && !ra->nh.next)
1570
    {
1571
      switch (rta_get_u16(a[RTA_ENCAP_TYPE]))
1572
	{
1573
	  case LWTUNNEL_ENCAP_MPLS:
1574
	    {
1575
	      struct rtattr *enca[BIRD_RTA_MAX];
1576
	      nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
1577
	      nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
1578
	      labels = rta_get_mpls(enca[RTA_DST], ra->nh.label);
1579
	      break;
1580
	    }
1581
	  default:
1582
	    SKIP("unknown encapsulation method %d\n", rta_get_u16(a[RTA_ENCAP_TYPE]));
1583
	    break;
1584
	}
1585
    }
1586

  
1587
  if (labels < 0)
1588
  {
1589
    log(L_WARN "KRT: Too long MPLS stack received, ignoring.");
1590
    ra->nh.labels = 0;
1591
  }
1592
  else
1593
    ra->nh.labels = labels;
1594

  
1595
  rte *e = rte_get_temp(ra);
1596
  e->net = net;
1597
  e->u.krt.src = src;
1598
  e->u.krt.proto = i->rtm_protocol;
1599
  e->u.krt.seen = 0;
1600
  e->u.krt.best = 0;
1601
  e->u.krt.metric = 0;
1602

  
1406 1603
  if (i->rtm_scope != def_scope)
1407 1604
    {
1408 1605
      ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + sizeof(eattr));
......
1416 1613
      ea->attrs[0].u.data = i->rtm_scope;
1417 1614
    }
1418 1615

  
1616
  if (a[RTA_PRIORITY])
1617
    e->u.krt.metric = rta_get_u32(a[RTA_PRIORITY]);
1618

  
1419 1619
  if (a[RTA_PREFSRC])
1420 1620
    {
1421 1621
      ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]);
......
1527 1727
    else
1528 1728
      log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
1529 1729
  nl_parse_end(&s);
1730

  
1731
  nl_parse_begin(&s, 1, 1);
1732
  nl_request_dump(AF_MPLS, RTM_GETROUTE);
1733
  while (h = nl_get_scan())
1734
    if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
1735
      nl_parse_route(&s, h);
1736
    else
1737
      log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
1738
  nl_parse_end(&s);
1530 1739
}
1531 1740

  
1532 1741
/*
sysdep/unix/krt.c
1153 1153
  {
1154 1154
  case NET_IP4:	p->af = AF_INET; break;
1155 1155
  case NET_IP6:	p->af = AF_INET6; break;
1156
  default:	ASSERT(0);
1156
  case NET_MPLS: p->af = AF_MPLS; break;
1157
  default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break;
1157 1158
  }
1158 1159

  
1159 1160
  add_tail(&krt_proto_list, &p->krt_node);
......
1264 1265
  .template =		"kernel%d",
1265 1266
  .attr_class =		EAP_KRT,
1266 1267
  .preference =		DEF_PREF_INHERITED,
1267
  .channel_mask =	NB_IP,
1268
  .channel_mask =	NB_IP | NB_MPLS,
1268 1269
  .proto_size =		sizeof(struct krt_proto),
1269 1270
  .config_size =	sizeof(struct krt_config),
1270 1271
  .preconfig =		krt_preconfig,

Also available in: Unified diff