]> git.puffer.fish Git - mirror/frr.git/commitdiff
Merge bgpd changeset 1184 from Zebra repository by Rivo Nurges.
authorhasso <hasso>
Thu, 20 May 2004 10:20:02 +0000 (10:20 +0000)
committerhasso <hasso>
Thu, 20 May 2004 10:20:02 +0000 (10:20 +0000)
bgpd/ChangeLog
bgpd/bgp_attr.c
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h
bgpd/bgp_packet.c

index cdcd83b9958ca556db8762a5025a86ebda90e7df..3adb996bcf1d51fac39183a29bbdf1967c8482f3 100644 (file)
@@ -1,3 +1,8 @@
+2004-05-20  Akihiro Mizutani <mizutani@net-chef.net>
+
+       * bgp_ecommunity.c: Transit ecommunity support.
+       * bgp_ecommunity.c: Fix for unknown community crush.
+
 2005-05-20 Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
 
        * *: Maximum prefix threshold support.
index 91a0e07ce1b1e95020739ba3d1318c074a2a04d6..7d48374d969b1094595f92c28058a07c27bdd296 100644 (file)
@@ -1653,19 +1653,67 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) 
       && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
     {
-      if (attr->ecommunity->size * 8 > 255)
+      if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
        {
-         stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
-         stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
-         stream_putw (s, attr->ecommunity->size * 8);
+         if (attr->ecommunity->size * 8 > 255)
+           {
+             stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+             stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+             stream_putw (s, attr->ecommunity->size * 8);
+           }
+         else
+           {
+             stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+             stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+             stream_putc (s, attr->ecommunity->size * 8);
+           }
+         stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8);
        }
       else
        {
-         stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
-         stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
-         stream_putc (s, attr->ecommunity->size * 8);
+         u_char *pnt;
+         int tbit;
+         int ecom_tr_size = 0;
+         int i;
+
+         for (i = 0; i < attr->ecommunity->size; i++)
+           {
+             pnt = attr->ecommunity->val + (i * 8);
+             tbit = *pnt;
+
+             if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
+               continue;
+
+             ecom_tr_size++;
+           }
+
+         if (ecom_tr_size)
+           {
+             if (ecom_tr_size * 8 > 255)
+               {
+                 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+                 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+                 stream_putw (s, ecom_tr_size * 8);
+               }
+             else
+               {
+                 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+                 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+                 stream_putc (s, ecom_tr_size * 8);
+               }
+
+             for (i = 0; i < attr->ecommunity->size; i++)
+               {
+                 pnt = attr->ecommunity->val + (i * 8);
+                 tbit = *pnt;
+
+                 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
+                   continue;
+
+                 stream_put (s, pnt, 8);
+               }
+           }
        }
-      stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8);
     }
 
   /* Unknown transit attribute. */
index 2f9cc9459df1bd58b3596eb186636bfacee629e8..4adbcf52c904d77316debd188209525e07a2aa1a 100644 (file)
@@ -158,6 +158,15 @@ ecommunity_dup (struct ecommunity *ecom)
   return new;
 }
 
+/* Retrun string representation of communities attribute. */
+char *
+ecommunity_str (struct ecommunity *ecom)
+{
+  if (! ecom->str)
+    ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
+  return ecom->str;
+}
+
 /* Merge two Extended Communities Attribute structure.  */
 struct ecommunity *
 ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2)
@@ -559,24 +568,30 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
 
   for (i = 0; i < ecom->size; i++)
     {
+      /* Space between each value.  */
+      if (! first)
+       str_buf[str_pnt++] = ' ';
+
       pnt = ecom->val + (i * 8);
 
       /* High-order octet of type. */
       encode = *pnt++;
       if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP)
        {
-         if (str_buf)
-           XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-         return "Unknown";
+         len = sprintf (str_buf + str_pnt, "?");
+         str_pnt += len;
+         first = 0;
+         continue;
        }
       
       /* Low-order octet of type. */
       type = *pnt++;
       if (type !=  ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN)
        {
-         if (str_buf)
-           XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-         return "Unknown";
+         len = sprintf (str_buf + str_pnt, "?");
+         str_pnt += len;
+         first = 0;
+         continue;
        }
 
       switch (format)
@@ -591,9 +606,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
          prefix = "";
          break;
        default:
-         if (str_buf)
-           XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-         return "Unknown";
+         prefix = "";
          break;
        }
 
@@ -604,10 +617,6 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
          str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size);
        }
 
-      /* Space between each value.  */
-      if (! first)
-       str_buf[str_pnt++] = ' ';
-
       /* Put string into buffer.  */
       if (encode == ECOMMUNITY_ENCODE_AS)
        {
@@ -639,3 +648,33 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format)
     }
   return str_buf;
 }
+
+int
+ecommunity_match (struct ecommunity *ecom1, struct ecommunity *ecom2)
+{
+  int i = 0;
+  int j = 0;
+
+  if (ecom1 == NULL && ecom2 == NULL)
+    return 1;
+
+  if (ecom1 == NULL || ecom2 == NULL)
+    return 0;
+
+  if (ecom1->size < ecom2->size)
+    return 0;
+
+  /* Every community on com2 needs to be on com1 for this to match */
+  while (i < ecom1->size && j < ecom2->size)
+    {
+      if (memcmp (ecom1->val + i, ecom2->val + j, ECOMMUNITY_SIZE) == 0)
+        j++;
+      i++;
+    }
+
+  if (j == ecom2->size)
+    return 1;
+  else
+    return 0;
+}
+
index 678d13082f64ecf73298f4cf1bd14106b8d8a03a..e266471f9266e651f230ff12336d91f33a60ae2a 100644 (file)
@@ -34,6 +34,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 /* Extended Communities value is eight octet long.  */
 #define ECOMMUNITY_SIZE                        8
 
+/* Extended Communities type flag.  */
+#define ECOMMUNITY_FLAG_NON_TRANSITIVE      0x40  
+
 /* Extended Communities attribute.  */
 struct ecommunity
 {
@@ -70,3 +73,5 @@ void ecommunity_unintern (struct ecommunity *);
 unsigned int ecommunity_hash_make (struct ecommunity *);
 struct ecommunity *ecommunity_str2com (char *, int, int);
 char *ecommunity_ecom2str (struct ecommunity *, int);
+int ecommunity_match (struct ecommunity *, struct ecommunity *);
+char *ecommunity_str (struct ecommunity *);
index 9995c02ceaaff49b0790c178eaa0bc311732a566..341a192cd2adad037047091d0c48e97c53bfd1ab 100644 (file)
@@ -273,7 +273,7 @@ bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
 #endif /* MPLS_VPN */
 
       if (STREAM_REMAIN (s) 
-         <= (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
+         < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
        break;
 
       if (stream_empty (s))