]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_attr.c
frr: Remove HAVE_IPV6 from code base
[mirror_frr.git] / bgpd / bgp_attr.c
index 24bd526ce3de10e397c96f7be53b2ab0fb64e70a..0e03392fafc5d05c5974a48127f5166f0e1f6204 100644 (file)
@@ -216,10 +216,16 @@ cluster_init (void)
 static void
 cluster_finish (void)
 {
+  hash_clean (cluster_hash, (void (*)(void *))cluster_free);
   hash_free (cluster_hash);
   cluster_hash = NULL;
 }
 
+static struct hash *encap_hash = NULL;
+#if ENABLE_BGP_VNC
+static struct hash *vnc_hash = NULL;
+#endif
+
 struct bgp_attr_encap_subtlv *
 encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
 {
@@ -287,14 +293,10 @@ encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
     struct bgp_attr_encap_subtlv *p;
     struct bgp_attr_encap_subtlv *q;
 
-    if (!h1 && !h2)
-       return 1;
-    if (h1 && !h2)
-       return 0;
-    if (!h1 && h2)
-       return 0;
     if (h1 == h2)
        return 1;
+    if (h1 == NULL || h2 == NULL)
+       return 0;
 
     for (p = h1; p; p = p->next) {
        for (q = h2; q; q = q->next) {
@@ -325,6 +327,96 @@ encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2)
     return 1;
 }
 
+static void *
+encap_hash_alloc (void *p)
+{
+  /* Encap structure is already allocated.  */
+  return p;
+}
+
+typedef enum 
+{
+  ENCAP_SUBTLV_TYPE,
+#if ENABLE_BGP_VNC
+  VNC_SUBTLV_TYPE
+#endif
+} encap_subtlv_type;
+
+static struct bgp_attr_encap_subtlv *
+encap_intern (struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
+{
+  struct bgp_attr_encap_subtlv *find;
+  struct hash *hash = encap_hash;
+#if ENABLE_BGP_VNC
+  if (type == VNC_SUBTLV_TYPE)
+    hash = vnc_hash;
+#endif
+
+  find = hash_get (hash, encap, encap_hash_alloc);
+  if (find != encap)
+    encap_free (encap);
+  find->refcnt++;
+
+  return find;
+}
+
+static void
+encap_unintern (struct bgp_attr_encap_subtlv **encapp, encap_subtlv_type type)
+{
+  struct bgp_attr_encap_subtlv *encap = *encapp;
+  if (encap->refcnt)
+    encap->refcnt--;
+
+  if (encap->refcnt == 0)
+    {
+      struct hash *hash = encap_hash;
+#if ENABLE_BGP_VNC
+      if (type == VNC_SUBTLV_TYPE)
+        hash = vnc_hash;
+#endif
+      hash_release (hash, encap);
+      encap_free (encap);
+      *encapp = NULL;
+    }
+}
+
+static unsigned int
+encap_hash_key_make (void *p)
+{
+  const struct bgp_attr_encap_subtlv * encap = p;
+
+  return jhash(encap->value, encap->length, 0);
+}
+
+static int
+encap_hash_cmp (const void *p1, const void *p2)
+{
+  return encap_same((struct bgp_attr_encap_subtlv *)p1,
+                    (struct bgp_attr_encap_subtlv *)p2);
+}
+
+static void
+encap_init (void)
+{
+  encap_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
+#if ENABLE_BGP_VNC
+  vnc_hash = hash_create (encap_hash_key_make, encap_hash_cmp);
+#endif
+}
+
+static void
+encap_finish (void)
+{
+  hash_clean (encap_hash, (void (*)(void *))encap_free);
+  hash_free (encap_hash);
+  encap_hash = NULL;
+#if ENABLE_BGP_VNC
+  hash_clean (vnc_hash, (void (*)(void *))encap_free);
+  hash_free (vnc_hash);
+  vnc_hash = NULL;
+#endif
+}
+
 /* Unknown transit attribute. */
 static struct hash *transit_hash;
 
@@ -414,6 +506,7 @@ transit_init (void)
 static void
 transit_finish (void)
 {
+  hash_clean (transit_hash, (void (*)(void *))transit_free);
   hash_free (transit_hash);
   transit_hash = NULL;
 }
@@ -432,16 +525,6 @@ bgp_attr_extra_free (struct attr *attr)
 {
   if (attr->extra)
     {
-      if (attr->extra->encap_subtlvs) {
-       encap_free(attr->extra->encap_subtlvs);
-       attr->extra->encap_subtlvs = NULL;
-      }
-#if ENABLE_BGP_VNC
-      if (attr->extra->vnc_subtlvs) {
-       encap_free(attr->extra->vnc_subtlvs);
-       attr->extra->vnc_subtlvs = NULL;
-      }
-#endif
       XFREE (MTYPE_ATTR_EXTRA, attr->extra);
       attr->extra = NULL;
     }
@@ -479,28 +562,12 @@ bgp_attr_dup (struct attr *new, struct attr *orig)
       memset(new->extra, 0, sizeof(struct attr_extra));
       if (orig->extra) {
         *new->extra = *orig->extra;
-        if (orig->extra->encap_subtlvs) {
-          new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
-        }
-#if ENABLE_BGP_VNC
-      if (orig->extra->vnc_subtlvs) {
-       new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
-      }
-#endif
       }
     }
   else if (orig->extra)
     {
       new->extra = bgp_attr_extra_new();
       *new->extra = *orig->extra;
-      if (orig->extra->encap_subtlvs) {
-       new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
-      }
-#if ENABLE_BGP_VNC
-      if (orig->extra->vnc_subtlvs) {
-       new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
-      }
-#endif
     }
 }
 
@@ -521,6 +588,12 @@ bgp_attr_deep_dup (struct attr *new, struct attr *orig)
         new->extra->cluster = cluster_dup(orig->extra->cluster);
       if (orig->extra->transit)
         new->extra->transit = transit_dup(orig->extra->transit);
+      if (orig->extra->encap_subtlvs)
+       new->extra->encap_subtlvs = encap_tlv_dup(orig->extra->encap_subtlvs);
+#if ENABLE_BGP_VNC
+      if (orig->extra->vnc_subtlvs)
+       new->extra->vnc_subtlvs = encap_tlv_dup(orig->extra->vnc_subtlvs);
+#endif
     }
 }
 
@@ -541,6 +614,12 @@ bgp_attr_deep_free (struct attr *attr)
         cluster_free(attr->extra->cluster);
       if (attr->extra->transit)
         transit_free(attr->extra->transit);
+      if (attr->extra->encap_subtlvs) 
+       encap_free(attr->extra->encap_subtlvs);
+#if ENABLE_BGP_VNC
+      if (attr->extra->vnc_subtlvs)
+       encap_free(attr->extra->vnc_subtlvs);
+#endif
     }
 }
 
@@ -597,12 +676,15 @@ attrhash_key_make (void *p)
         MIX(cluster_hash_key_make (extra->cluster));
       if (extra->transit)
         MIX(transit_hash_key_make (extra->transit));
-
-#ifdef HAVE_IPV6
+      if (extra->encap_subtlvs)
+        MIX(encap_hash_key_make (extra->encap_subtlvs));
+#if ENABLE_BGP_VNC
+      if (extra->vnc_subtlvs)
+        MIX(encap_hash_key_make (extra->vnc_subtlvs));
+#endif
       MIX(extra->mp_nexthop_len);
       key = jhash(extra->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
       key = jhash(extra->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
-#endif /* HAVE_IPV6 */
     }
 
   return key;
@@ -631,11 +713,9 @@ attrhash_cmp (const void *p1, const void *p2)
           && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
           && ae1->weight == ae2->weight
           && ae1->tag == ae2->tag
-#ifdef HAVE_IPV6
           && ae1->mp_nexthop_len == ae2->mp_nexthop_len
           && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
           && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
-#endif /* HAVE_IPV6 */
           && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
           && ae1->ecommunity == ae2->ecommunity
           && ae1->cluster == ae2->cluster
@@ -662,9 +742,20 @@ attrhash_init (void)
   attrhash = hash_create (attrhash_key_make, attrhash_cmp);
 }
 
+/*
+ * special for hash_clean below
+ */
+static void
+attr_vfree (void *attr)
+{
+  bgp_attr_extra_free ((struct attr *)attr);
+  XFREE (MTYPE_ATTR, attr);
+}
+
 static void
 attrhash_finish (void)
 {
+  hash_clean(attrhash, attr_vfree);
   hash_free (attrhash);
   attrhash = NULL;
 }
@@ -699,13 +790,12 @@ bgp_attr_hash_alloc (void *p)
     {
       attr->extra = bgp_attr_extra_new ();
       *attr->extra = *val->extra;
-
-      if (attr->extra->encap_subtlvs) {
-       attr->extra->encap_subtlvs = encap_tlv_dup(attr->extra->encap_subtlvs);
+      if (val->extra->encap_subtlvs) {
+        val->extra->encap_subtlvs = NULL;
       }
 #if ENABLE_BGP_VNC
-      if (attr->extra->vnc_subtlvs) {
-       attr->extra->vnc_subtlvs = encap_tlv_dup(attr->extra->vnc_subtlvs);
+      if (val->extra->vnc_subtlvs) {
+        val->extra->vnc_subtlvs = NULL;
       }
 #endif
     }
@@ -760,11 +850,27 @@ bgp_attr_intern (struct attr *attr)
           else
             attre->transit->refcnt++;
         }
+      if (attre->encap_subtlvs)
+        {
+          if (! attre->encap_subtlvs->refcnt)
+            attre->encap_subtlvs = encap_intern (attre->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+          else
+            attre->encap_subtlvs->refcnt++;
+        }
+#if ENABLE_BGP_VNC
+      if (attre->vnc_subtlvs)
+        {
+          if (! attre->vnc_subtlvs->refcnt)
+            attre->vnc_subtlvs = encap_intern (attre->vnc_subtlvs, VNC_SUBTLV_TYPE);
+          else
+            attre->vnc_subtlvs->refcnt++;
+        }
+#endif
     }
   
   find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
   find->refcnt++;
-  
+
   return find;
 }
 
@@ -798,6 +904,14 @@ bgp_attr_refcount (struct attr *attr)
 
       if (attre->transit)
        attre->transit->refcnt++;
+
+      if (attre->encap_subtlvs)
+       attre->encap_subtlvs->refcnt++;
+
+#if ENABLE_BGP_VNC
+      if (attre->vnc_subtlvs)
+       attre->vnc_subtlvs->refcnt++;
+#endif
     }
   attr->refcnt++;
   return attr;
@@ -817,9 +931,7 @@ bgp_attr_default_set (struct attr *attr, u_char origin)
   attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
   attr->extra->tag = 0;
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
-#ifdef HAVE_IPV6
   attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
-#endif
 
   return attr;
 }
@@ -880,9 +992,7 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
     }
 
   attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
-#ifdef HAVE_IPV6
   attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
-#endif
   if (! as_set || atomic_aggregate)
     attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
   attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
@@ -923,6 +1033,14 @@ bgp_attr_unintern_sub (struct attr *attr)
       
       if (attr->extra->transit)
         transit_unintern (attr->extra->transit);
+
+      if (attr->extra->encap_subtlvs)
+        encap_unintern (&attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+
+#if ENABLE_BGP_VNC
+      if (attr->extra->vnc_subtlvs)
+        encap_unintern (&attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
+#endif
     }
 }
 
@@ -963,9 +1081,15 @@ void
 bgp_attr_flush (struct attr *attr)
 {
   if (attr->aspath && ! attr->aspath->refcnt)
-    aspath_free (attr->aspath);
+    {
+      aspath_free (attr->aspath);
+      attr->aspath = NULL;
+    }
   if (attr->community && ! attr->community->refcnt)
-    community_free (attr->community);
+    {
+      community_free (attr->community);
+      attr->community = NULL;
+    }
   if (attr->extra)
     {
       struct attr_extra *attre = attr->extra;
@@ -973,14 +1097,26 @@ bgp_attr_flush (struct attr *attr)
       if (attre->ecommunity && ! attre->ecommunity->refcnt)
         ecommunity_free (&attre->ecommunity);
       if (attre->cluster && ! attre->cluster->refcnt)
-        cluster_free (attre->cluster);
+        {
+          cluster_free (attre->cluster);
+          attre->cluster = NULL;
+        }
       if (attre->transit && ! attre->transit->refcnt)
-        transit_free (attre->transit);
-      encap_free(attre->encap_subtlvs);
-      attre->encap_subtlvs = NULL;
+        {
+          transit_free (attre->transit);
+          attre->transit = NULL;
+        }
+      if (attre->encap_subtlvs && ! attre->encap_subtlvs->refcnt)
+        {
+          encap_free(attre->encap_subtlvs);
+          attre->encap_subtlvs = NULL;
+        }
 #if ENABLE_BGP_VNC
-      encap_free(attre->vnc_subtlvs);
-      attre->vnc_subtlvs = NULL;
+      if (attre->vnc_subtlvs && ! attre->vnc_subtlvs->refcnt)
+        {
+          encap_free(attre->vnc_subtlvs);
+          attre->vnc_subtlvs = NULL;
+        }
 #endif
     }
 }
@@ -1119,8 +1255,7 @@ const u_int8_t attr_flags_values [] = {
   [BGP_ATTR_AS4_PATH] =         BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
   [BGP_ATTR_AS4_AGGREGATOR] =   BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
 };
-static const size_t attr_flags_values_max =
-  sizeof (attr_flags_values) / sizeof (attr_flags_values[0]);
+static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
 
 static int
 bgp_attr_flag_invalid (struct bgp_attr_parser_args *args)
@@ -1718,8 +1853,6 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
   safi_t safi;
   bgp_size_t nlri_len;
   size_t start;
-  int ret;
-  int num_mp_pfx = 0;
   struct stream *s;
   struct peer *const peer = args->peer;  
   struct attr *const attr = args->attr;
@@ -1768,7 +1901,6 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
       stream_getl (s); /* RD low */
       stream_get (&attre->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
       break;
-#ifdef HAVE_IPV6
     case BGP_ATTR_NHLEN_IPV6_GLOBAL:
     case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
       if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL)
@@ -1808,7 +1940,6 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
          attre->mp_nexthop_len = IPV6_MAX_BYTELEN;
        }
       break;
-#endif /* HAVE_IPV6 */
     default:
       zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d", 
                 __func__, peer->host, attre->mp_nexthop_len);
@@ -1837,18 +1968,6 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
                  __func__, peer->host);
       return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
     }
-  if (safi != SAFI_MPLS_LABELED_VPN)
-    {
-      ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
-                                   nlri_len, &num_mp_pfx);
-      if (ret < 0) 
-        {
-          zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
-                     __func__, peer->host);
-         return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
-       }
-    }
 
   mp_update->afi = afi;
   mp_update->safi = safi;
@@ -1872,8 +1991,6 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
   afi_t afi;
   safi_t safi;
   u_int16_t withdraw_len;
-  int ret;
-  int num_mp_pfx = 0;
   struct peer *const peer = args->peer;  
   struct attr *const attr = args->attr;
   const bgp_size_t length = args->length;
@@ -1889,14 +2006,6 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
   
   withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
 
-  if (safi != SAFI_MPLS_LABELED_VPN)
-    {
-      ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
-                                  withdraw_len, &num_mp_pfx);
-      if (ret < 0)
-       return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
-    }
-
   mp_withdraw->afi = afi;
   mp_withdraw->safi = safi;
   mp_withdraw->nlri = stream_pnt (s);
@@ -2493,10 +2602,18 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
       if (ret != BGP_ATTR_PARSE_PROCEED)
        return ret;
     }
-
-  /* Finally intern unknown attribute. */
-  if (attr->extra && attr->extra->transit)
-    attr->extra->transit = transit_intern (attr->extra->transit);
+  if (attr->extra) 
+    {
+      /* Finally intern unknown attribute. */
+      if (attr->extra->transit)
+        attr->extra->transit = transit_intern (attr->extra->transit);
+      if (attr->extra->encap_subtlvs)
+        attr->extra->encap_subtlvs = encap_intern (attr->extra->encap_subtlvs, ENCAP_SUBTLV_TYPE);
+#if ENABLE_BGP_VNC
+      if (attr->extra->vnc_subtlvs)
+        attr->extra->vnc_subtlvs = encap_intern (attr->extra->vnc_subtlvs, VNC_SUBTLV_TYPE);
+#endif
+    }
 
   return BGP_ATTR_PARSE_PROCEED;
 }
@@ -2544,7 +2661,6 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
          break;
        }
       break;
-#ifdef HAVE_IPV6
     case AFI_IP6:
       switch (safi)
       {
@@ -2591,7 +2707,6 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
        break;
       }
       break;
-#endif /*HAVE_IPV6*/
     default:
       break;
     }
@@ -3184,6 +3299,7 @@ bgp_attr_init (void)
   ecommunity_init ();
   cluster_init ();
   transit_init ();
+  encap_init ();
 }
 
 void
@@ -3195,6 +3311,7 @@ bgp_attr_finish (void)
   ecommunity_finish ();
   cluster_finish ();
   transit_finish ();
+  encap_finish ();
 }
 
 /* Make attribute packet. */
@@ -3232,11 +3349,7 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
 
   /* Nexthop attribute. */
   /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
-  if(prefix != NULL
-#ifdef HAVE_IPV6
-     && prefix->family != AF_INET6
-#endif /* HAVE_IPV6 */
-     )
+  if(prefix != NULL && prefix->family != AF_INET6)
     {
       stream_putc (s, BGP_ATTR_FLAG_TRANS);
       stream_putc (s, BGP_ATTR_NEXT_HOP);
@@ -3299,7 +3412,6 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
       stream_put (s, attr->community->val, attr->community->size * 4);
     }
 
-#ifdef HAVE_IPV6
   /* Add a MP_NLRI attribute to dump the IPv6 next hop */
   if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
      (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||
@@ -3332,7 +3444,6 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
       /* Set MP attribute length. */
       stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
     }
-#endif /* HAVE_IPV6 */
 
   /* Return total size of attribute. */
   len = stream_get_endp (s) - cp - 2;