Revision 42a0c054 proto/bgp/attrs.c

View differences:

proto/bgp/attrs.c
247 247
  return ((len % 4) == 0) ? 0 : WITHDRAW;
248 248
}
249 249

  
250

  
251 250
static int
252 251
bgp_check_cluster_list(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
253 252
{
......
281 280
  return IGNORE;
282 281
}
283 282

  
283
static int
284
bgp_check_ext_community(struct bgp_proto *p UNUSED, byte *a UNUSED, int len)
285
{
286
  return ((len % 8) == 0) ? 0 : WITHDRAW;
287
}
288

  
289

  
284 290
static struct attr_desc bgp_attr_table[] = {
285 291
  { NULL, -1, 0, 0, 0,								/* Undefined */
286 292
    NULL, NULL },
......
311 317
    bgp_check_reach_nlri, NULL },
312 318
  { "mp_unreach_nlri", -1, BAF_OPTIONAL, EAF_TYPE_OPAQUE, 1,			/* BA_MP_UNREACH_NLRI */
313 319
    bgp_check_unreach_nlri, NULL },
314
  {  .name = NULL },								/* BA_EXTENDED_COMM */
320
  { "ext_community", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_EC_SET, 1,	/* BA_EXT_COMMUNITY */
321
    bgp_check_ext_community, NULL },
315 322
  { "as4_path", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,		/* BA_AS4_PATH */
316 323
    NULL, NULL },
317 324
  { "as4_aggregator", -1, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_OPAQUE, 1,	/* BA_AS4_PATH */
......
468 475
unsigned int
469 476
bgp_encode_attrs(struct bgp_proto *p, byte *w, ea_list *attrs, int remains)
470 477
{
471
  unsigned int i, code, flags;
478
  unsigned int i, code, type, flags;
472 479
  byte *start = w;
473 480
  int len, rv;
474 481

  
......
477 484
      eattr *a = &attrs->attrs[i];
478 485
      ASSERT(EA_PROTO(a->id) == EAP_BGP);
479 486
      code = EA_ID(a->id);
487

  
480 488
#ifdef IPV6
481 489
      /* When talking multiprotocol BGP, the NEXT_HOP attributes are used only temporarily. */
482 490
      if (code == BA_NEXT_HOP)
......
559 567

  
560 568
      /* Standard path continues here ... */
561 569

  
570
      type = a->type & EAF_TYPE_MASK;
562 571
      flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
563 572
      len = bgp_get_attr_len(a);
564 573

  
565
      /* Skip empty int sets */ 
566
      if (((a->type & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) && (len == 0))
574
      /* Skip empty sets */ 
575
      if (((type == EAF_TYPE_INT_SET) || (type == EAF_TYPE_EC_SET)) && (len == 0))
567 576
	continue; 
568 577

  
569 578
      if (remains < len + 4)
......
572 581
      rv = bgp_encode_attr_hdr(w, flags, code, len);
573 582
      ADVANCE(w, remains, rv);
574 583

  
575
      switch (a->type & EAF_TYPE_MASK)
584
      switch (type)
576 585
	{
577 586
	case EAF_TYPE_INT:
578 587
	case EAF_TYPE_ROUTER_ID:
......
589 598
	    break;
590 599
	  }
591 600
	case EAF_TYPE_INT_SET:
601
	case EAF_TYPE_EC_SET:
592 602
	  {
593
	    u32 *z = (u32 *)a->u.ptr->data;
603
	    u32 *z = int_set_get_data(a->u.ptr);
594 604
	    int i;
595 605
	    for(i=0; i<len; i+=4)
596 606
	      put_u32(w+i, *z++);
......
624 634
  return (*x < *y) ? -1 : (*x > *y) ? 1 : 0;
625 635
}
626 636

  
627
static void
628
bgp_normalize_set(u32 *dest, u32 *src, unsigned cnt)
637
static inline void
638
bgp_normalize_int_set(u32 *dest, u32 *src, unsigned cnt)
629 639
{
630 640
  memcpy(dest, src, sizeof(u32) * cnt);
631 641
  qsort(dest, cnt, sizeof(u32), (int(*)(const void *, const void *)) bgp_compare_u32);
632 642
}
633 643

  
644
static int
645
bgp_compare_ec(const u32 *xp, const u32 *yp)
646
{
647
  u64 x = ec_get(xp, 0);
648
  u64 y = ec_get(yp, 0);
649
  return (x < y) ? -1 : (x > y) ? 1 : 0;
650
}
651

  
652
static inline void
653
bgp_normalize_ec_set(struct adata *ad, u32 *src, int internal)
654
{
655
  u32 *dst = int_set_get_data(ad);
656

  
657
  /* Remove non-transitive communities (EC_TBIT active) on external sessions */
658
  if (! internal)
659
    {
660
      int len = int_set_get_size(ad);
661
      u32 *t = dst;
662
      int i;
663

  
664
      for (i=0; i < len; i += 2)
665
	{
666
	  if (src[i] & EC_TBIT)
667
	    continue;
668
	  
669
	  *t++ = src[i];
670
	  *t++ = src[i+1];
671
	}
672

  
673
      ad->length = (t - dst) * 4;
674
    }
675
  else
676
    memcpy(dst, src, ad->length);
677

  
678
  qsort(dst, ad->length / 8, 8, (int(*)(const void *, const void *)) bgp_compare_ec);
679
}
680

  
634 681
static void
635 682
bgp_rehash_buckets(struct bgp_proto *p)
636 683
{
......
763 810
	  {
764 811
	    struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
765 812
	    z->length = d->u.ptr->length;
766
	    bgp_normalize_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / 4);
813
	    bgp_normalize_int_set((u32 *) z->data, (u32 *) d->u.ptr->data, z->length / 4);
814
	    d->u.ptr = z;
815
	    break;
816
	  }
817
	case EAF_TYPE_EC_SET:
818
	  {
819
	    struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
820
	    z->length = d->u.ptr->length;
821
	    bgp_normalize_ec_set(z, (u32 *) d->u.ptr->data, p->is_internal);
767 822
	    d->u.ptr = z;
768 823
	    break;
769 824
	  }
......
1447 1502
	  ipa_ntoh(*(ip_addr *)ad->data);
1448 1503
	  break;
1449 1504
	case EAF_TYPE_INT_SET:
1505
	case EAF_TYPE_EC_SET:
1450 1506
	  {
1451 1507
	    u32 *z = (u32 *) ad->data;
1452 1508
	    for(i=0; i<ad->length/4; i++)

Also available in: Unified diff