[quagga-users 7575] Re: redistributing a NAT'ted route

Andrew J. Schorr aschorr at telemetry-investments.com
Fri Sep 22 16:29:55 IST 2006


Sorry, that patch (to support redistributing NATted routes into BGP) was still
missing minor changes to one file, and I'd like to get it right in the archive
(in case somebody later wants to take a look at this).  My sense is that
there's not much interest at the moment...

So I hope here's the final version.  I think it should at least compile.

Regards,
Andy
-------------- next part --------------
Index: bgpd/bgp_route.c
===================================================================
RCS file: /var/cvsroot/quagga/bgpd/bgp_route.c,v
retrieving revision 1.54
diff -b -u -p -r1.54 bgp_route.c
--- bgpd/bgp_route.c	14 Sep 2006 03:38:17 -0000	1.54
+++ bgpd/bgp_route.c	22 Sep 2006 19:26:09 -0000
@@ -4879,7 +4879,7 @@ ALIAS (no_ipv6_aggregate_address_summary
 
 /* Redistribute route treatment. */
 void
-bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
+bgp_redistribute_add (struct prefix *p_orig, struct in_addr *nexthop,
 		      u_int32_t metric, u_char type)
 {
   struct bgp *bgp;
@@ -4904,10 +4904,14 @@ bgp_redistribute_add (struct prefix *p, 
 
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
     {
-      afi = family2afi (p->family);
+      afi = family2afi (p_orig->family);
 
       if (bgp->redist[afi][type])
 	{
+	  struct prefix pc;
+
+	  prefix_copy(&pc, p_orig);
+
 	  /* Copy attribute for modification. */
 	  attr_new = attr;
 
@@ -4922,7 +4926,7 @@ bgp_redistribute_add (struct prefix *p, 
 
               SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE);
 
-	      ret = route_map_apply (bgp->rmap[afi][type].map, p, RMAP_BGP,
+	      ret = route_map_apply (bgp->rmap[afi][type].map, &pc, RMAP_BGP,
 				     &info);
 
               bgp->peer_self->rmap_type = 0;
@@ -4934,12 +4938,12 @@ bgp_redistribute_add (struct prefix *p, 
 
 		  /* Unintern original. */
 		  aspath_unintern (attr.aspath);
-		  bgp_redistribute_delete (p, type);
+		  bgp_redistribute_delete (&pc, type, 0);
 		  return;
 		}
 	    }
 
-         bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL);
+         bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, &pc, NULL);
 	  new_attr = bgp_attr_intern (&attr_new);
  
  	  for (bi = bn->info; bi; bi = bi->next)
@@ -4962,13 +4966,13 @@ bgp_redistribute_add (struct prefix *p, 
  		  bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
  
  		  /* Rewrite BGP route information. */
- 		  bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
+ 		  bgp_aggregate_decrement (bgp, &pc, bi, afi, SAFI_UNICAST);
  		  bgp_attr_unintern (bi->attr);
  		  bi->attr = new_attr;
  		  bi->uptime = time (NULL);
  
  		  /* Process change. */
- 		  bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
+ 		  bgp_aggregate_increment (bgp, &pc, bi, afi, SAFI_UNICAST);
  		  bgp_process (bgp, bn, afi, SAFI_UNICAST);
  		  bgp_unlock_node (bn);
  		  aspath_unintern (attr.aspath);
@@ -4984,7 +4988,7 @@ bgp_redistribute_add (struct prefix *p, 
 	  new->attr = new_attr;
 	  new->uptime = time (NULL);
 
-	  bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
+	  bgp_aggregate_increment (bgp, &pc, new, afi, SAFI_UNICAST);
 	  bgp_info_add (bn, new);
 	  bgp_unlock_node (bn);
 	  bgp_process (bgp, bn, afi, SAFI_UNICAST);
@@ -4996,21 +5000,50 @@ bgp_redistribute_add (struct prefix *p, 
 }
 
 void
-bgp_redistribute_delete (struct prefix *p, u_char type)
+bgp_redistribute_delete (struct prefix *p_orig, u_char type, int need_rmap)
 {
   struct bgp *bgp;
   struct listnode *node, *nnode;
   afi_t afi;
   struct bgp_node *rn;
   struct bgp_info *ri;
+  struct attr attr;
+
+  if (need_rmap)
+    {
+      bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
+      attr.med = 0;
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+    }
 
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
     {
-      afi = family2afi (p->family);
+      afi = family2afi (p_orig->family);
 
       if (bgp->redist[afi][type])
 	{
-         rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL);
+	  struct prefix pc;
+
+	  prefix_copy(&pc, p_orig);
+
+	  /* must call route_map_apply in case 'ip nat' is occurring */
+	  if (need_rmap && bgp->rmap[afi][type].map)
+	    {
+	      struct bgp_info info;
+	      struct attr attr_new;
+
+	      attr_new = attr;
+	      if (bgp->redist_metric_flag[afi][type])
+		attr_new.med = bgp->redist_metric[afi][type];
+	      info.peer = bgp->peer_self;
+	      info.attr = &attr_new;
+	      SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE);
+	      route_map_apply(bgp->rmap[afi][type].map, &pc, RMAP_BGP, &info);
+	      bgp->peer_self->rmap_type = 0;
+	      bgp_attr_flush(&attr_new);
+	    }
+
+         rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, &pc, NULL);
 
 	  for (ri = rn->info; ri; ri = ri->next)
 	    if (ri->peer == bgp->peer_self
@@ -5019,13 +5052,15 @@ bgp_redistribute_delete (struct prefix *
 
 	  if (ri)
 	    {
-	      bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
+	      bgp_aggregate_decrement (bgp, &pc, ri, afi, SAFI_UNICAST);
 	      bgp_info_delete (rn, ri);
 	      bgp_process (bgp, rn, afi, SAFI_UNICAST);
 	    }
 	  bgp_unlock_node (rn);
 	}
     }
+  if (need_rmap)
+    aspath_unintern (attr.aspath);
 }
 
 /* Withdraw specified route type's route. */
Index: bgpd/bgp_route.h
===================================================================
RCS file: /var/cvsroot/quagga/bgpd/bgp_route.h,v
retrieving revision 1.14
diff -b -u -p -r1.14 bgp_route.h
--- bgpd/bgp_route.h	7 Sep 2006 00:24:49 -0000	1.14
+++ bgpd/bgp_route.h	22 Sep 2006 19:26:09 -0000
@@ -171,7 +171,7 @@ extern int bgp_nlri_parse (struct peer *
 extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
 
 extern void bgp_redistribute_add (struct prefix *, struct in_addr *, u_int32_t, u_char);
-extern void bgp_redistribute_delete (struct prefix *, u_char);
+extern void bgp_redistribute_delete (struct prefix *, u_char, int need_rmap);
 extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
 
 extern void bgp_static_delete (struct bgp *);
Index: bgpd/bgp_routemap.c
===================================================================
RCS file: /var/cvsroot/quagga/bgpd/bgp_routemap.c,v
retrieving revision 1.21
diff -b -u -p -r1.21 bgp_routemap.c
--- bgpd/bgp_routemap.c	18 Feb 2006 10:49:04 -0000	1.21
+++ bgpd/bgp_routemap.c	22 Sep 2006 19:26:09 -0000
@@ -890,6 +890,64 @@ struct route_map_rule_cmd route_set_ip_n
   route_set_ip_nexthop_free
 };
 
+/* `set ip nat IP_PREFIX' */
+
+struct rmap_ip_nat_set
+{
+  struct prefix_ipv4 p;
+};
+
+static route_map_result_t
+route_set_ip_nat (void *rule, struct prefix *prefix,
+		  route_map_object_t type, void *object)
+{
+  if (type == RMAP_BGP)
+    {
+      struct bgp_info *bgp_info = object;
+      struct peer *peer = bgp_info->peer;
+
+      if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE))
+	{
+	  struct rmap_ip_nat_set *rins = rule;
+	  prefix_copy(prefix, (struct prefix *)&rins->p);
+	}
+    }
+  return RMAP_OKAY;
+}
+
+/* Route map `ip nat' compile function.  Given string is converted
+   to struct prefix_ipv4 structure. */
+static void *
+route_set_ip_nat_compile (const char *arg)
+{
+  struct rmap_ip_nat_set *rins;
+  struct prefix_ipv4 p;
+
+  if (str2prefix_ipv4(arg, &p) == 0)
+    return NULL;
+
+  rins = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_ip_nat_set));
+  rins->p = p;
+
+  return rins;
+}
+
+/* Free route map's compiled `ip nat' value. */
+static void
+route_set_ip_nat_free (void *rule)
+{
+  struct rmap_ip_nat_set *rins = rule;
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rins);
+}
+
+/* Route map commands for ip nat set. */
+struct route_map_rule_cmd route_set_ip_nat_cmd =
+{
+  "ip nat",
+  route_set_ip_nat,
+  route_set_ip_nat_compile,
+  route_set_ip_nat_free
+};
 /* `set local-preference LOCAL_PREF' */
 
 /* Set local preference. */
@@ -2789,6 +2847,47 @@ ALIAS (no_set_ip_nexthop,
        "Next hop address\n"
        "IP address of next hop\n")
 
+DEFUN (set_ip_nat,
+       set_ip_nat_cmd,
+       "set ip nat A.B.C.D/M",
+       SET_STR
+       IP_STR
+       "NAT prefix translation\n"
+       "Prefix to install into BGP\n")
+{
+  struct prefix_ipv4 p;
+
+  if (str2prefix_ipv4 (argv[0], &p) == 0)
+    {
+      vty_out (vty, "%% Malformed NAT prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+ 
+  return bgp_route_set_add (vty, vty->index, "ip nat", argv[0]);
+}
+
+DEFUN (no_set_ip_nat,
+       no_set_ip_nat_cmd,
+       "no set ip nat",
+       NO_STR
+       SET_STR
+       "NAT prefix translation\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ip nat", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "ip nat", argv[0]);
+}
+
+ALIAS (no_set_ip_nat,
+       no_set_ip_nat_val_cmd,
+       "no set ip nat A.B.C.D",
+       NO_STR
+       SET_STR
+       IP_STR
+       "NAT prefix translation\n"
+       "Prefix to install into BGP\n")
+
 DEFUN (set_metric,
        set_metric_cmd,
        "set metric <0-4294967295>",
@@ -3551,6 +3650,7 @@ bgp_route_map_init (void)
   route_map_install_match (&route_match_origin_cmd);
 
   route_map_install_set (&route_set_ip_nexthop_cmd);
+  route_map_install_set (&route_set_ip_nat_cmd);
   route_map_install_set (&route_set_local_pref_cmd);
   route_map_install_set (&route_set_weight_cmd);
   route_map_install_set (&route_set_metric_cmd);
@@ -3612,6 +3712,9 @@ bgp_route_map_init (void)
   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
   install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
   install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
+  install_element (RMAP_NODE, &set_ip_nat_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nat_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nat_val_cmd);
   install_element (RMAP_NODE, &set_local_pref_cmd);
   install_element (RMAP_NODE, &no_set_local_pref_cmd);
   install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
Index: bgpd/bgp_zebra.c
===================================================================
RCS file: /var/cvsroot/quagga/bgpd/bgp_zebra.c,v
retrieving revision 1.11
diff -b -u -p -r1.11 bgp_zebra.c
--- bgpd/bgp_zebra.c	28 Jun 2005 12:44:17 -0000	1.11
+++ bgpd/bgp_zebra.c	22 Sep 2006 19:26:09 -0000
@@ -235,7 +235,7 @@ zebra_read_ipv4 (int command, struct zcl
   if (command == ZEBRA_IPV4_ROUTE_ADD)
     bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
   else
-    bgp_redistribute_delete ((struct prefix *)&p, api.type);
+    bgp_redistribute_delete ((struct prefix *)&p, api.type, 1);
 
   return 0;
 }
@@ -293,7 +293,7 @@ zebra_read_ipv6 (int command, struct zcl
   if (command == ZEBRA_IPV6_ROUTE_ADD)
     bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
   else
-    bgp_redistribute_delete ((struct prefix *) &p, api.type);
+    bgp_redistribute_delete ((struct prefix *) &p, api.type, 1);
   
   return 0;
 }


More information about the Quagga-users mailing list