From: Dinesh Dutt <[email protected]>

Currently, BGP route maps don't support interface match. This is a problem
for commands such as redistribite connected that cannot exclude routes from
specific interfaces (such as mgmt interfaces).

Signed-off-by: Dinesh Dutt <[email protected]>
---
 bgpd/bgp_attr.h     |  1 +
 bgpd/bgp_route.c    |  3 +-
 bgpd/bgp_route.h    |  2 +-
 bgpd/bgp_routemap.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 bgpd/bgp_zebra.c    | 18 ++++++++---
 vtysh/extract.pl.in |  2 +-
 6 files changed, 109 insertions(+), 8 deletions(-)

diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 8018104..e63202c 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -109,6 +109,7 @@ struct attr
   struct in_addr nexthop;
   u_int32_t med;
   u_int32_t local_pref;
+  u_int32_t nh_ifindex;
   
   /* Path origin attribute */
   u_char origin;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index fc84ea6..69811fb 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -5556,7 +5556,7 @@ ALIAS (no_ipv6_aggregate_address_summary_only,
 /* Redistribute route treatment. */
 void
 bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
-                     const struct in6_addr *nexthop6,
+                     const struct in6_addr *nexthop6, unsigned int ifindex,
                      u_int32_t metric, u_char type)
 {
   struct bgp *bgp;
@@ -5574,6 +5574,7 @@ bgp_redistribute_add (struct prefix *p, const struct 
in_addr *nexthop,
   bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
   if (nexthop)
     attr.nexthop = *nexthop;
+  attr.nh_ifindex = ifindex;
 
 #ifdef HAVE_IPV6
   if (nexthop6)
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index ef7ffe2..a97fe11 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -216,7 +216,7 @@ extern int bgp_nlri_parse (struct peer *, struct attr *, 
struct bgp_nlri *);
 extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
 
 extern void bgp_redistribute_add (struct prefix *, const struct in_addr *,
-                                 const struct in6_addr *,
+                                 const struct in6_addr *, unsigned int ifindex,
                                  u_int32_t, u_char);
 extern void bgp_redistribute_delete (struct prefix *, u_char);
 extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index b41d235..320393d 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -64,7 +64,7 @@ o Cisco route-map
 
  match as-path          :  Done
        community        :  Done
-       interface        :  Not yet
+       interface        :  Done
        ip address       :  Done
        ip next-hop      :  Done
        ip route-source  :  Done
@@ -1005,6 +1005,57 @@ struct route_map_rule_cmd route_match_probability_cmd =
   route_match_probability_free
 };
 
+/* `match interface IFNAME' */
+/* Match function should return 1 if match is success else return
+   zero. */
+static route_map_result_t
+route_match_interface (void *rule, struct prefix *prefix,
+                      route_map_object_t type, void *object)
+{
+  struct interface *ifp;
+  struct bgp_info *info;
+
+  if (type == RMAP_BGP)
+    {
+      info = object;
+
+      if (!info || !info->attr)
+       return RMAP_NOMATCH;
+
+      ifp = if_lookup_by_name ((char *)rule);
+
+      if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex)
+       return RMAP_NOMATCH;
+
+      return RMAP_MATCH;
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `interface' match statement.  `arg' should be
+   interface name. */
+static void *
+route_match_interface_compile (const char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `interface' value. */
+static void
+route_match_interface_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_interface_cmd =
+{
+  "interface",
+  route_match_interface,
+  route_match_interface_compile,
+  route_match_interface_free
+};
+
 /* } */
 
 /* `set ip next-hop IP_ADDRESS' */
@@ -3314,6 +3365,40 @@ ALIAS (no_match_origin,
        "local IGP\n"
        "unknown heritage\n")
 
+DEFUN (match_interface,
+       match_interface_cmd,
+       "match interface WORD",
+       MATCH_STR
+       "Match first hop interface of route\n"
+       "Interface name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "interface", argv[0],
+                             RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_interface,
+       no_match_interface_cmd,
+       "no match interface",
+       NO_STR
+       MATCH_STR
+       "Match first hop interface of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "interface", NULL,
+                                  RMAP_EVENT_MATCH_DELETED);
+
+  return bgp_route_match_delete (vty, vty->index, "interface", argv[0],
+                                RMAP_EVENT_MATCH_DELETED);
+}
+
+ALIAS (no_match_interface,
+       no_match_interface_val_cmd,
+       "no match interface WORD",
+       NO_STR
+       MATCH_STR
+       "Match first hop interface of route\n"
+       "Interface name\n")
+
 DEFUN (set_ip_nexthop,
        set_ip_nexthop_cmd,
        "set ip next-hop A.B.C.D",
@@ -4305,6 +4390,7 @@ bgp_route_map_init (void)
   route_map_install_match (&route_match_metric_cmd);
   route_map_install_match (&route_match_origin_cmd);
   route_map_install_match (&route_match_probability_cmd);
+  route_map_install_match (&route_match_interface_cmd);
 
   route_map_install_set (&route_set_ip_nexthop_cmd);
   route_map_install_set (&route_set_local_pref_cmd);
@@ -4369,6 +4455,9 @@ bgp_route_map_init (void)
   install_element (RMAP_NODE, &match_probability_cmd);
   install_element (RMAP_NODE, &no_match_probability_cmd);
   install_element (RMAP_NODE, &no_match_probability_val_cmd);
+  install_element (RMAP_NODE, &match_interface_cmd);
+  install_element (RMAP_NODE, &no_match_interface_cmd);
+  install_element (RMAP_NODE, &no_match_interface_val_cmd);
 
   install_element (RMAP_NODE, &set_ip_nexthop_cmd);
   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index bc52ab1..339ed12 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -386,6 +386,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, 
zebra_size_t length,
   struct zapi_ipv4 api;
   struct in_addr nexthop;
   struct prefix_ipv4 p;
+  unsigned int ifindex;
 
   s = zclient->ibuf;
   nexthop.s_addr = 0;
@@ -410,7 +411,11 @@ zebra_read_ipv4 (int command, struct zclient *zclient, 
zebra_size_t length,
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
     {
       api.ifindex_num = stream_getc (s);
-      stream_getl (s); /* ifindex, unused */
+      ifindex = stream_getl (s); /* ifindex, unused */
+    }
+  else
+    {
+      ifindex = 0;
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
@@ -431,7 +436,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, 
zebra_size_t length,
                     inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
                     api.metric);
        }
-      bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL,
+      bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex,
                           api.metric, api.type);
     }
   else
@@ -463,6 +468,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, 
zebra_size_t length,
   struct zapi_ipv6 api;
   struct in6_addr nexthop;
   struct prefix_ipv6 p;
+  unsigned int ifindex;
 
   s = zclient->ibuf;
   memset (&nexthop, 0, sizeof (struct in6_addr));
@@ -487,7 +493,11 @@ zebra_read_ipv6 (int command, struct zclient *zclient, 
zebra_size_t length,
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
     {
       api.ifindex_num = stream_getc (s);
-      stream_getl (s); /* ifindex, unused */
+      ifindex = stream_getl (s); /* ifindex, unused */
+    }
+  else
+    {
+      ifindex = 0;
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
@@ -514,7 +524,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, 
zebra_size_t length,
                     inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
                     api.metric);
        }
-      bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop,
+      bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex,
                            api.metric, api.type);
     }
   else
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index f9a6dc6..8415e7e 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -177,7 +177,7 @@ foreach (@ARGV) {
     }
 }
 
-my $bad_cli_stomps = 90;
+my $bad_cli_stomps = 93;
 # Currently we have $bad_cli_stomps.  This was determined by
 # running this script and counting up the collisions from what
 # was returned.
-- 
1.9.1


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to