]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Match routes by type under route-maps
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Fri, 28 Sep 2018 08:51:50 +0000 (11:51 +0300)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Tue, 2 Oct 2018 07:57:45 +0000 (10:57 +0300)
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_routemap.c
lib/routemap.c
lib/routemap.h

index 0b4355805cf6961c75b3887f79faff5d59bdc8c5..3f29e879dfc70091c90e0a3bdd0b41f62743d783 100644 (file)
@@ -548,6 +548,45 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
        route_match_ip_next_hop_prefix_list_compile,
        route_match_ip_next_hop_prefix_list_free};
 
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+                            route_map_object_t type, void *object)
+{
+       struct bgp_info *bgp_info;
+
+       if (type == RMAP_BGP && prefix->family == AF_INET) {
+               bgp_info = (struct bgp_info *)object;
+               if (!bgp_info || !bgp_info->attr)
+                       return RMAP_DENYMATCH;
+
+               /* If nexthop interface's index can't be resolved and nexthop is
+                  set to any address then mark it as type `blackhole`.
+                  This logic works for matching kernel/static routes like:
+                  `ip route add blackhole 10.0.0.1`. */
+               if (bgp_info->attr->nexthop.s_addr == INADDR_ANY
+                   && !bgp_info->attr->nh_ifindex)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+       "ip next-hop type", route_match_ip_next_hop_type,
+       route_match_ip_next_hop_type_compile,
+       route_match_ip_next_hop_type_free};
+
 /* `match ip route-source prefix-list PREFIX_LIST' */
 
 static route_map_result_t
@@ -2372,6 +2411,53 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
        route_match_ipv6_address_prefix_list_compile,
        route_match_ipv6_address_prefix_list_free};
 
+/* `match ipv6 next-hop type <TYPE>' */
+
+static route_map_result_t
+route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
+                             route_map_object_t type, void *object)
+{
+       struct bgp_info *bgp_info;
+       struct in6_addr *addr = rule;
+
+       if (type == RMAP_BGP && prefix->family == AF_INET6) {
+               bgp_info = (struct bgp_info *)object;
+               if (!bgp_info || !bgp_info->attr)
+                       return RMAP_DENYMATCH;
+
+               if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)
+                   && !bgp_info->attr->nh_ifindex)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_type_compile(const char *arg)
+{
+       struct in6_addr *address;
+       int ret;
+
+       address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
+
+       ret = inet_pton(AF_INET6, "::0", address);
+       if (!ret) {
+               XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
+               return NULL;
+       }
+
+       return address;
+}
+
+static void route_match_ipv6_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
+       "ipv6 next-hop type", route_match_ipv6_next_hop_type,
+       route_match_ipv6_next_hop_type_compile,
+       route_match_ipv6_next_hop_type_free};
+
 /* `set ipv6 nexthop global IP_ADDRESS' */
 
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
@@ -4645,12 +4731,18 @@ void bgp_route_map_init(void)
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ip_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
        route_map_match_ipv6_address_hook(generic_match_add);
        route_map_no_match_ipv6_address_hook(generic_match_delete);
 
        route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
        route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ipv6_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+
        route_map_match_metric_hook(generic_match_add);
        route_map_no_match_metric_hook(generic_match_delete);
 
@@ -4676,6 +4768,7 @@ void bgp_route_map_init(void)
        route_map_install_match(&route_match_ip_route_source_cmd);
        route_map_install_match(&route_match_ip_address_prefix_list_cmd);
        route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
+       route_map_install_match(&route_match_ip_next_hop_type_cmd);
        route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
        route_map_install_match(&route_match_aspath_cmd);
        route_map_install_match(&route_match_community_cmd);
@@ -4791,6 +4884,7 @@ void bgp_route_map_init(void)
        route_map_install_match(&route_match_ipv6_address_cmd);
        route_map_install_match(&route_match_ipv6_next_hop_cmd);
        route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
+       route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
        route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
index bec6d389e534298d66db39fe83940f9e1af40e43..2111a4f4da262e7037d71fb1f05c16e38cca34ea 100644 (file)
@@ -111,6 +111,20 @@ struct route_map_match_set_hooks {
                                                const char *arg,
                                                route_map_event_t type);
 
+       /* match ip next hop type */
+       int (*match_ip_next_hop_type)(struct vty *vty,
+                                            struct route_map_index *index,
+                                            const char *command,
+                                            const char *arg,
+                                            route_map_event_t type);
+
+       /* no match ip next hop type */
+       int (*no_match_ip_next_hop_type)(struct vty *vty,
+                                               struct route_map_index *index,
+                                               const char *command,
+                                               const char *arg,
+                                               route_map_event_t type);
+
        /* match ipv6 address */
        int (*match_ipv6_address)(struct vty *vty,
                                  struct route_map_index *index,
@@ -138,6 +152,19 @@ struct route_map_match_set_hooks {
                                                 const char *arg,
                                                 route_map_event_t type);
 
+       /* match ipv6 next-hop type */
+       int (*match_ipv6_next_hop_type)(struct vty *vty,
+                                             struct route_map_index *index,
+                                             const char *command,
+                                             const char *arg,
+                                             route_map_event_t type);
+
+       /* no match ipv6next-hop type */
+       int (*no_match_ipv6_next_hop_type)(struct vty *vty,
+                                          struct route_map_index *index,
+                                          const char *command, const char *arg,
+                                          route_map_event_t type);
+
        /* match metric */
        int (*match_metric)(struct vty *vty, struct route_map_index *index,
                            const char *command, const char *arg,
@@ -275,6 +302,22 @@ void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
        rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func;
 }
 
+/* match ip next hop type */
+void route_map_match_ip_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type))
+{
+       rmap_match_set_hook.match_ip_next_hop_type = func;
+}
+
+/* no match ip next hop type */
+void route_map_no_match_ip_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type))
+{
+       rmap_match_set_hook.no_match_ip_next_hop_type = func;
+}
+
 /* match ipv6 address */
 void route_map_match_ipv6_address_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
@@ -308,6 +351,22 @@ void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)(
        rmap_match_set_hook.no_match_ipv6_address_prefix_list = func;
 }
 
+/* match ipv6 next-hop type */
+void route_map_match_ipv6_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type))
+{
+       rmap_match_set_hook.match_ipv6_next_hop_type = func;
+}
+
+/* no match ipv6 next-hop type */
+void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type))
+{
+       rmap_match_set_hook.no_match_ipv6_next_hop_type = func;
+}
+
 /* match metric */
 void route_map_match_metric_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
@@ -2028,6 +2087,45 @@ DEFUN (no_match_ip_next_hop_prefix_list,
        return CMD_SUCCESS;
 }
 
+DEFUN(match_ip_next_hop_type, match_ip_next_hop_type_cmd,
+      "match ip next-hop type <blackhole>",
+      MATCH_STR IP_STR
+      "Match next-hop address of route\n"
+      "Match entries by type\n"
+      "Blackhole\n")
+{
+       int idx_word = 4;
+       VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+       if (rmap_match_set_hook.match_ip_next_hop_type)
+               return rmap_match_set_hook.match_ip_next_hop_type(
+                       vty, index, "ip next-hop type", argv[idx_word]->arg,
+                       RMAP_EVENT_MATCH_ADDED);
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
+      "no match ip next-hop type [<blackhole>]",
+      NO_STR MATCH_STR IP_STR
+      "Match next-hop address of route\n"
+      "Match entries by type\n"
+      "Blackhole\n")
+{
+       int idx_word = 5;
+       VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+       if (rmap_match_set_hook.no_match_ip_next_hop) {
+               if (argc <= idx_word)
+                       return rmap_match_set_hook.no_match_ip_next_hop(
+                               vty, index, "ip next-hop type", NULL,
+                               RMAP_EVENT_MATCH_DELETED);
+               return rmap_match_set_hook.no_match_ip_next_hop(
+                       vty, index, "ip next-hop type", argv[idx_word]->arg,
+                       RMAP_EVENT_MATCH_DELETED);
+       }
+       return CMD_SUCCESS;
+}
+
 
 DEFUN (match_ipv6_address,
        match_ipv6_address_cmd,
@@ -2106,6 +2204,39 @@ DEFUN (no_match_ipv6_address_prefix_list,
        return CMD_SUCCESS;
 }
 
+DEFUN(match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
+      "match ipv6 next-hop type <blackhole>",
+      MATCH_STR IPV6_STR
+      "Match address of route\n"
+      "Match entries by type\n"
+      "Blackhole\n")
+{
+       int idx_word = 4;
+       VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+       if (rmap_match_set_hook.match_ipv6_next_hop_type)
+               return rmap_match_set_hook.match_ipv6_next_hop_type(
+                       vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
+                       RMAP_EVENT_MATCH_ADDED);
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
+      "no match ipv6 next-hop type [<blackhole>]",
+      NO_STR MATCH_STR IPV6_STR
+      "Match address of route\n"
+      "Match entries by type\n"
+      "Blackhole\n")
+{
+       int idx_word = 5;
+       VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+       if (rmap_match_set_hook.no_match_ipv6_next_hop_type)
+               return rmap_match_set_hook.no_match_ipv6_next_hop_type(
+                       vty, index, "ipv6 next-hop type", argv[idx_word]->arg,
+                       RMAP_EVENT_MATCH_DELETED);
+       return CMD_SUCCESS;
+}
 
 DEFUN (match_metric,
        match_metric_cmd,
@@ -2873,12 +3004,18 @@ void route_map_init(void)
        install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
        install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
 
+       install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
+       install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
+
        install_element(RMAP_NODE, &match_ipv6_address_cmd);
        install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
 
        install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
        install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
 
+       install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
+       install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
+
        install_element(RMAP_NODE, &match_metric_cmd);
        install_element(RMAP_NODE, &no_match_metric_cmd);
 
index a193e325360c675be31041665fd3b47bf68ac572..c654806b44932d0c0d8a037f4ab4ffa90a86863d 100644 (file)
@@ -283,6 +283,14 @@ extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)(
 extern void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
        const char *arg, route_map_event_t type));
+/* match ip next hop type */
+extern void route_map_match_ip_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type));
+/* no match ip next hop type */
+extern void route_map_no_match_ip_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type));
 /* match ipv6 address */
 extern void route_map_match_ipv6_address_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
@@ -299,6 +307,14 @@ extern void route_map_match_ipv6_address_prefix_list_hook(int (*func)(
 extern void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
        const char *arg, route_map_event_t type));
+/* match ipv6 next-hop type */
+extern void route_map_match_ipv6_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type));
+/* no match ipv6 next-hop type */
+extern void route_map_no_match_ipv6_next_hop_type_hook(int (*func)(
+       struct vty *vty, struct route_map_index *index, const char *command,
+       const char *arg, route_map_event_t type));
 /* match metric */
 extern void route_map_match_metric_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,