[quagga-dev 11351] [PATCH 6/6] ripngd & lib: add administrative distance support

Feng Lu lu.feng at 6wind.com
Wed Jun 25 09:43:20 BST 2014


This is mostly a clone from RIP distance code.

Signed-off-by: Feng Lu <lu.feng at 6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux at 6wind.com>
---
 lib/memtypes.c           |    1 +
 ripngd/ripng_interface.c |    6 +-
 ripngd/ripng_zebra.c     |   17 ++-
 ripngd/ripngd.c          |  387 ++++++++++++++++++++++++++++++++++++++++++++--
 ripngd/ripngd.h          |   11 ++-
 5 files changed, 402 insertions(+), 20 deletions(-)

diff --git a/lib/memtypes.c b/lib/memtypes.c
index 47a3438..6ab7cb7 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -174,6 +174,7 @@ struct memory_list memory_list_ripng[] =
   { MTYPE_RIPNG_PEER,         "RIPng peer"			},
   { MTYPE_RIPNG_OFFSET_LIST,  "RIPng offset lst"		},
   { MTYPE_RIPNG_RTE_DATA,     "RIPng rte data"			},
+  { MTYPE_RIPNG_DISTANCE,     "RIPng distance"			},
   { -1, NULL }
 };
 
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index 3588463..0a6c513 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -380,7 +380,7 @@ ripng_apply_address_add (struct connected *ifc) {
   if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
       (ripng_enable_network_lookup2(ifc) >= 0))
     ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
-                           &address, ifc->ifp->ifindex, NULL);
+                           &address, ifc->ifp->ifindex, NULL, 0);
 
 }
 
@@ -701,13 +701,13 @@ ripng_connect_set (struct interface *ifp, int set)
         if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
             (ripng_enable_network_lookup2(connected) >= 0))
           ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
-                                  &address, connected->ifp->ifindex, NULL);
+                                  &address, connected->ifp->ifindex, NULL, 0);
       } else {
         ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
                                    &address, connected->ifp->ifindex);
         if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
           ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
-                                  &address, connected->ifp->ifindex, NULL);
+                                  &address, connected->ifp->ifindex, NULL, 0);
       }
     }
 }
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index 501f459..3813b95 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -92,6 +92,12 @@ ripng_zebra_ipv6_add (struct route_node *rp)
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = rinfo->metric;
 
+      if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT)
+        {
+          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+          api.distance = rinfo->distance;
+        }
+
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient,
                        (struct prefix_ipv6 *)&rp->p, &api);
 
@@ -146,6 +152,12 @@ ripng_zebra_ipv6_delete (struct route_node *rp)
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = rinfo->metric;
 
+      if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT)
+        {
+          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+          api.distance = rinfo->distance;
+        }
+
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient,
                        (struct prefix_ipv6 *)&rp->p, &api);
 
@@ -195,14 +207,15 @@ ripng_zebra_read_ipv6 (int command, struct zclient *zclient,
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
   else
-    api.distance = 0;
+    api.distance = 255;
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
     api.metric = stream_getl (s);
   else
     api.metric = 0;
 
   if (command == ZEBRA_IPV6_ROUTE_ADD)
-    ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
+    ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex,
+                            &nexthop, api.distance);
   else
     ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex);
 
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 12f62be..1b27966 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -759,6 +759,7 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
   int same = 0;
   struct list *list = NULL;
   struct listnode *node = NULL;
+  unsigned char old_dist, new_dist;
 
   /* Make prefix structure. */
   memset (&p, 0, sizeof (struct prefix_ipv6));
@@ -860,6 +861,9 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
   newinfo.nexthop = *nexthop;
   newinfo.metric = rte->metric;
   newinfo.tag = ntohs (rte->tag);
+  newinfo.distance = ripng_distance_apply (&newinfo);
+
+  new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIPNG_DISTANCE_DEFAULT;
 
   /* Check to see whether there is already RIPng route on the table. */
   if ((list = rp->info) != NULL)
@@ -889,8 +893,24 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
                * with the new one in below. */
               break;
 
-            /* Metrics are same. Keep "rinfo" null and the new route
-             * is added in the ECMP list in below. */
+            /* Metrics are same. We compare the distances. */
+            old_dist = rinfo->distance ? \
+                       rinfo->distance : ZEBRA_RIPNG_DISTANCE_DEFAULT;
+
+            if (new_dist > old_dist)
+              {
+                /* New route has a greater distance. Discard it. */
+                route_unlock_node (rp);
+                return;
+              }
+
+            if (new_dist < old_dist)
+              /* New route has a smaller distance. Replace the ECMP list
+               * with the new one in below. */
+              break;
+
+            /* Metrics and distances are both same. Keep "rinfo" null and
+             * the new route is added in the ECMP list in below. */
           }
       }
 
@@ -900,6 +920,16 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
       if (rinfo->type != ZEBRA_ROUTE_RIPNG
 	  && rinfo->metric != RIPNG_METRIC_INFINITY)
         {
+          old_dist = rinfo->distance;
+          /* Only routes directly connected to an interface (nexthop == 0)
+           * may have a valid NULL distance */
+          if (!IN6_IS_ADDR_UNSPECIFIED (&rinfo->nexthop))
+            old_dist = old_dist ? old_dist : ZEBRA_RIPNG_DISTANCE_DEFAULT;
+          /* If imported route does not have STRICT precedence,
+             mark it as a ghost */
+          if (new_dist <= old_dist && rte->metric != RIPNG_METRIC_INFINITY)
+            ripng_ecmp_replace (&newinfo);
+
           route_unlock_node (rp);
           return;
         }
@@ -934,13 +964,23 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
       same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) 
 	      && (rinfo->ifindex == ifp->ifindex));
 
+      old_dist = rinfo->distance ? \
+                 rinfo->distance : ZEBRA_RIPNG_DISTANCE_DEFAULT;
+
       /* Next, compare the metrics.  If the datagram is from the same
-	 router as the existing route, and the new metric is different
-	 than the old one; or, if the new metric is lower than the old
-	 one; do the following actions: */
-      if ((same && rinfo->metric != rte->metric) ||
-	  rte->metric < rinfo->metric)
-	{
+         router as the existing route, and the new metric is different
+         than the old one; or, if the new metric is lower than the old
+         one, or if the tag has been changed; or if there is a route
+         with a lower administrave distance; or an update of the
+         distance on the actual route; do the following actions: */
+      if ((same && rinfo->metric != rte->metric)
+          || (rte->metric < rinfo->metric)
+          || ((same)
+              && (rinfo->metric == rte->metric)
+              && (newinfo.tag != rinfo->tag))
+          || (old_dist > new_dist)
+          || ((old_dist != new_dist) && same))
+        {
           if (listcount (list) == 1)
             {
               if (newinfo.metric != RIPNG_METRIC_INFINITY)
@@ -952,10 +992,33 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
             {
               if (newinfo.metric < rinfo->metric)
                 ripng_ecmp_replace (&newinfo);
-              else /* newinfo.metric > rinfo->metric */
+              else if (newinfo.metric > rinfo->metric)
+                ripng_ecmp_delete (rinfo);
+              else if (new_dist < old_dist)
+                ripng_ecmp_replace (&newinfo);
+              else if (new_dist > old_dist)
                 ripng_ecmp_delete (rinfo);
+              else
+                {
+                  int update = CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB) ? 1 : 0;
+
+                  assert (newinfo.metric != RIPNG_METRIC_INFINITY);
+
+                  RIPNG_TIMER_OFF (rinfo->t_timeout);
+                  RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
+                  memcpy (rinfo, &newinfo, sizeof (struct ripng_info));
+                  ripng_timeout_update (rinfo);
+
+                  if (update)
+                    ripng_zebra_ipv6_add (rp);
+
+                  /* - Set the route change flag on the first entry. */
+                  rinfo = listgetdata (listhead (list));
+                  SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED);
+                  ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
+                }
             }
-	}
+        }
       else /* same & no change */
         ripng_timeout_update (rinfo);
 
@@ -967,7 +1030,7 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
 /* Add redistributed route to RIPng table. */
 void
 ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, 
-			unsigned int ifindex, struct in6_addr *nexthop)
+    unsigned int ifindex, struct in6_addr *nexthop, unsigned char distance)
 {
   struct route_node *rp;
   struct ripng_info *rinfo = NULL, newinfo;
@@ -995,6 +1058,7 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
   newinfo.sub_type = sub_type;
   newinfo.ifindex = ifindex;
   newinfo.metric = 1;
+  newinfo.distance = distance;
   newinfo.rp = rp;
   if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
     newinfo.nexthop = *nexthop;
@@ -1905,7 +1969,10 @@ ripng_create (void)
   ripng->table = route_table_init ();
   ripng->route = route_table_init ();
   ripng->aggregate = route_table_init ();
- 
+
+  /* Initialize distance table. */
+  ripng->distance_table = route_table_init ();
+
   /* Make socket. */
   ripng->sock = ripng_make_socket ();
   if (ripng->sock < 0)
@@ -2050,6 +2117,8 @@ ripng_route_subtype_print (struct ripng_info *rinfo)
   return str;
 }
 
+static void ripng_distance_show (struct vty *vty);
+
 DEFUN (show_ipv6_ripng,
        show_ipv6_ripng_cmd,
        "show ipv6 ripng",
@@ -2228,6 +2297,8 @@ DEFUN (show_ipv6_ripng_status,
   vty_out (vty, "    Gateway          BadPackets BadRoutes  Distance Last Update%s", VTY_NEWLINE);
   ripng_peer_display (vty);
 
+  ripng_distance_show (vty);
+
   return CMD_SUCCESS;  
 }
 
@@ -2295,7 +2366,8 @@ DEFUN (ripng_route,
     }
   rp->info = (void *)1;
 
-  ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
+  ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL,
+                          0);
 
   return CMD_SUCCESS;
 }
@@ -2632,7 +2704,8 @@ DEFUN (ripng_default_information_originate,
     ripng->default_information = 1;
 
     str2prefix_ipv6 ("::/0", &p);
-    ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
+    ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL,
+                            0);
   }
 
   return CMD_SUCCESS;
@@ -2747,6 +2820,269 @@ ALIAS (no_ripng_ecmp_limit,
        "RIPng settings\n"
        "Equal Cost MultiPath\n")
 
+struct ripng_distance
+{
+  /* Distance value for the IPv6 source prefix. */
+  u_char distance;
+
+  /* Name of the IPv6 access-list to be matched. */
+  char *access_list;
+};
+
+static struct ripng_distance *
+ripng_distance_new (void)
+{
+  return XCALLOC (MTYPE_RIPNG_DISTANCE, sizeof (struct ripng_distance));
+}
+
+static void
+ripng_distance_free (struct ripng_distance *rdistance)
+{
+  XFREE (MTYPE_RIPNG_DISTANCE, rdistance);
+}
+
+static int
+ripng_distance_set (struct vty *vty, const char *distance_str,
+    const char *ipv6_str, const char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv6 p;
+  u_char distance;
+  struct route_node *rn;
+  struct ripng_distance *rdistance;
+
+  ret = str2prefix_ipv6 (ipv6_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  distance = atoi (distance_str);
+
+  /* Get RIPng distance node. */
+  rn = route_node_get (ripng->distance_table, (struct prefix *) &p);
+  if (rn->info)
+    {
+      rdistance = rn->info;
+      route_unlock_node (rn);
+    }
+  else
+    {
+      rdistance = ripng_distance_new ();
+      rn->info = rdistance;
+    }
+
+  /* Set distance value. */
+  rdistance->distance = distance;
+
+  /* Reset access-list configuration. */
+  if (rdistance->access_list)
+    {
+      free (rdistance->access_list);
+      rdistance->access_list = NULL;
+    }
+  if (access_list_str)
+    rdistance->access_list = strdup (access_list_str);
+
+  return CMD_SUCCESS;
+}
+
+static int
+ripng_distance_unset (struct vty *vty, const char *distance_str,
+    const char *ipv6_str, const char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv6 p;
+  struct route_node *rn;
+  struct ripng_distance *rdistance;
+
+  ret = str2prefix_ipv6 (ipv6_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rn = route_node_lookup (ripng->distance_table, (struct prefix *)&p);
+  if (! rn)
+    {
+      vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  rdistance = rn->info;
+
+  if (rdistance->access_list)
+    free (rdistance->access_list);
+  ripng_distance_free (rdistance);
+
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+static void
+ripng_distance_reset (void)
+{
+  struct route_node *rn;
+  struct ripng_distance *rdistance;
+
+  for (rn = route_top (ripng->distance_table); rn; rn = route_next (rn))
+    if ((rdistance = rn->info) != NULL)
+      {
+        if (rdistance->access_list)
+          free (rdistance->access_list);
+        ripng_distance_free (rdistance);
+        rn->info = NULL;
+        route_unlock_node (rn);
+      }
+}
+
+/* Apply RIPng information to distance method. */
+u_char
+ripng_distance_apply (struct ripng_info *rinfo)
+{
+  struct route_node *rn;
+  struct prefix_ipv6 p;
+  struct ripng_distance *rdistance;
+  struct access_list *alist;
+
+  if (! ripng)
+    return 0;
+
+  memset (&p, 0, sizeof (struct prefix_ipv6));
+  p.family = AF_INET6;
+  p.prefix = rinfo->from;
+  p.prefixlen = IPV6_MAX_BITLEN;
+
+  /* Check source address. */
+  rn = route_node_match (ripng->distance_table, (struct prefix *) &p);
+  if (rn)
+    {
+      rdistance = rn->info;
+      route_unlock_node (rn);
+
+      if (rdistance->access_list)
+        {
+          alist = access_list_lookup (AFI_IP6, rdistance->access_list);
+          if (alist == NULL)
+            return 0;
+          if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
+            return 0;
+
+          return rdistance->distance;
+        }
+      else
+        return rdistance->distance;
+    }
+
+  if (ripng->distance)
+    return ripng->distance;
+
+  return 0;
+}
+
+static void
+ripng_distance_show (struct vty *vty)
+{
+  struct route_node *rn;
+  struct ripng_distance *rdistance;
+  int header = 1;
+  char buf[BUFSIZ];
+
+  vty_out (vty, "  Distance: (default is %d)%s",
+           ripng->distance ? ripng->distance : ZEBRA_RIPNG_DISTANCE_DEFAULT,
+           VTY_NEWLINE);
+
+  for (rn = route_top (ripng->distance_table); rn; rn = route_next (rn))
+    if ((rdistance = rn->info) != NULL)
+      {
+        if (header)
+          {
+            vty_out (vty, "    Address             Distance  List%s",
+                     VTY_NEWLINE);
+            header = 0;
+          }
+        sprintf (buf, "%s/%d", inet6_ntoa (rn->p.u.prefix6), rn->p.prefixlen);
+        vty_out (vty, "    %s%s    %28d  %s%s",
+                 buf, VTY_NEWLINE, rdistance->distance,
+                 rdistance->access_list ? rdistance->access_list : "",
+                 VTY_NEWLINE);
+      }
+}
+
+DEFUN (ripng_distance,
+       ripng_distance_cmd,
+       "distance <1-255>",
+       "Administrative distance\n"
+       "Distance value\n")
+{
+  ripng->distance = atoi (argv[0]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ripng_distance,
+       no_ripng_distance_cmd,
+       "no distance <1-255>",
+       NO_STR
+       "Administrative distance\n"
+       "Distance value\n")
+{
+  ripng->distance = 0;
+  return CMD_SUCCESS;
+}
+
+DEFUN (ripng_distance_source,
+       ripng_distance_source_cmd,
+       "distance <1-255> IPV6ADDR",
+       "Administrative distance\n"
+       "Distance value\n"
+       "IPv6 source prefix\n")
+{
+  ripng_distance_set (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ripng_distance_source,
+       no_ripng_distance_source_cmd,
+       "no distance <1-255> IPV6ADDR",
+       NO_STR
+       "Administrative distance\n"
+       "Distance value\n"
+       "IPv6 source prefix\n")
+{
+  ripng_distance_unset (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ripng_distance_source_access_list,
+       ripng_distance_source_access_list_cmd,
+       "distance <1-255> IPV6ADDR WORD",
+       "Administrative distance\n"
+       "Distance value\n"
+       "IPv6 source prefix\n"
+       "Access list name\n")
+{
+  ripng_distance_set (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ripng_distance_source_access_list,
+       no_ripng_distance_source_access_list_cmd,
+       "no distance <1-255> IPV6ADDR WORD",
+       NO_STR
+       "Administrative distance\n"
+       "Distance value\n"
+       "IPv6 source prefix\n"
+       "Access list name\n")
+{
+  ripng_distance_unset (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
 /* RIPng configuration write function. */
 static int
 ripng_config_write (struct vty *vty)
@@ -2755,6 +3091,7 @@ ripng_config_write (struct vty *vty)
   void ripng_redistribute_write (struct vty *, int);
   int write = 0;
   struct route_node *rp;
+  struct ripng_distance *rdistance;
 
   if (ripng)
     {
@@ -2816,6 +3153,18 @@ ripng_config_write (struct vty *vty)
 		 VTY_NEWLINE);
 #endif /* 0 */
 
+      /* Distance configuration. */
+      if (ripng->distance)
+        vty_out (vty, " distance %d%s", ripng->distance, VTY_NEWLINE);
+
+      /* RIPng source IPv6 prefix distance configuration. */
+      for (rp = route_top (ripng->distance_table); rp; rp = route_next (rp))
+        if ((rdistance = rp->info) != NULL)
+          vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance,
+                   inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen,
+                   rdistance->access_list ? rdistance->access_list : "",
+                   VTY_NEWLINE);
+
       /* RIPng ECMP configuration. */
       if (ripng->ecmp)
         vty_out (vty, " ripng equal-cost %d%s", ripng->ripng_multipath_limit,
@@ -3002,6 +3351,9 @@ ripng_clean()
       if (ripng->route_map[i].name)
         free (ripng->route_map[i].name);
 
+    ripng_distance_reset ();
+    route_table_finish (ripng->distance_table);
+
     XFREE (MTYPE_ROUTE_TABLE, ripng->table);
     XFREE (MTYPE_ROUTE_TABLE, ripng->route);
     XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
@@ -3160,6 +3512,13 @@ ripng_init ()
   install_element (RIPNG_NODE, &no_ripng_ecmp_limit_val_cmd);
   install_element (RIPNG_NODE, &no_ripng_ecmp_limit_cmd);
 
+  install_element (RIPNG_NODE, &ripng_distance_cmd);
+  install_element (RIPNG_NODE, &no_ripng_distance_cmd);
+  install_element (RIPNG_NODE, &ripng_distance_source_cmd);
+  install_element (RIPNG_NODE, &no_ripng_distance_source_cmd);
+  install_element (RIPNG_NODE, &ripng_distance_source_access_list_cmd);
+  install_element (RIPNG_NODE, &no_ripng_distance_source_access_list_cmd);
+
   ripng_if_init ();
   ripng_debug_init ();
 
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 03f9866..fa04505 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -138,6 +138,10 @@ struct ripng
   unsigned int ecmp;
   unsigned int ripng_multipath_limit;
 
+  /* RIPng default distance. */
+  u_char distance;
+  struct route_table *distance_table;
+
   /* For redistribute route map. */
   struct
   {
@@ -209,6 +213,8 @@ struct ripng_info
   u_short tag_out;
 
   struct route_node *rp;
+
+  u_char distance;
 };
 
 #ifdef notyet
@@ -390,7 +396,8 @@ extern void ripng_info_free (struct ripng_info *rinfo);
 extern void ripng_event (enum ripng_event, int);
 extern int ripng_request (struct interface *ifp);
 extern void ripng_redistribute_add (int, int, struct prefix_ipv6 *,
-                                    unsigned int, struct in6_addr *);
+                                    unsigned int, struct in6_addr *,
+                                    unsigned char);
 extern void ripng_redistribute_delete (int, int, struct prefix_ipv6 *,
                                        unsigned int);
 extern void ripng_redistribute_withdraw (int type);
@@ -427,4 +434,6 @@ extern struct ripng_info *ripng_ecmp_add (struct ripng_info *);
 extern struct ripng_info *ripng_ecmp_replace (struct ripng_info *);
 extern struct ripng_info *ripng_ecmp_delete (struct ripng_info *);
 
+extern u_char ripng_distance_apply (struct ripng_info *);
+
 #endif /* _ZEBRA_RIPNG_RIPNGD_H */
-- 
1.7.4.4





More information about the Quagga-dev mailing list