]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: bgpd-route-map-match-interface.patch
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:40:47 +0000 (17:40 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:40:47 +0000 (17:40 -0700)
BGP: Add match interface support to BGP route-map.

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).

bgpd/bgp_attr.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_zebra.c

index 2d796b5b70083b571c17a28409fda577454b85eb..5aa0c39f952024d95c4e1e4fd8c046b341b7556a 100644 (file)
@@ -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;
index da9903a2a4ef6cc2b3d40d488e0a7d47c3370ed7..be6cb3b2598081f0bb5679eeac44640039f4795e 100644 (file)
@@ -5592,7 +5592,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;
@@ -5610,6 +5610,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)
index 23337961ecbaee528b9d02811d55d9da1e925dbe..905295b94e23b6950213c257582a5769d2aaaed0 100644 (file)
@@ -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);
index 3204daba517ec5b3be0afa51076730c2b58111fe..49cde8ea951d995a2ab8685794690ec3afac0798 100644 (file)
@@ -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
@@ -951,6 +951,58 @@ 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 nexthop *nexthop;
+  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' */
@@ -3361,6 +3413,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",
@@ -4334,6 +4420,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);
@@ -4398,6 +4485,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);
index c109eaba93f40c5413edbdebf1e3772925917df2..9391030c1e72137e99d73994af4f8e3c226ba0a7 100644 (file)
@@ -380,6 +380,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;
@@ -404,7 +405,7 @@ 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 */
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
@@ -425,7 +426,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
@@ -456,6 +457,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));
@@ -480,7 +482,7 @@ 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 */
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (s);
@@ -507,7 +509,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