]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
Merge pull request #4970 from shikenghua/prefer_global
[mirror_frr.git] / bgpd / bgp_routemap.c
index 7f1a9b71c137f6ba1b63426890785eb448c7bec8..cb3d79436dd1b7298b50d7f0b2714535fdcff318 100644 (file)
@@ -269,13 +269,16 @@ route_match_peer(void *rule, const struct prefix *prefix,
 
                /* If su='0.0.0.0' (command 'match peer local'), and it's a
                   NETWORK,
-                   REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
+                   REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
+                  => return RMAP_MATCH
                   */
                if (sockunion_same(su, &su_def)) {
                        int ret;
                        if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
                            || CHECK_FLAG(peer->rmap_type,
                                          PEER_RMAP_TYPE_REDISTRIBUTE)
+                           || CHECK_FLAG(peer->rmap_type,
+                                         PEER_RMAP_TYPE_AGGREGATE)
                            || CHECK_FLAG(peer->rmap_type,
                                          PEER_RMAP_TYPE_DEFAULT))
                                ret = RMAP_MATCH;
@@ -1207,10 +1210,26 @@ static void route_match_community_free(void *rule)
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
 }
 
+/*
+ * In routemap processing there is a need to add the
+ * name as a rule_key in the dependency table. Routemap
+ * lib is unaware of rule_key when exact-match clause
+ * is in use. routemap lib uses the compiled output to
+ * get the rule_key value.
+ */
+static void *route_match_get_community_key(void *rule)
+{
+       struct rmap_community *rcom;
+
+       rcom = rule;
+       return rcom->name;
+}
+
+
 /* Route map commands for community matching. */
 struct route_map_rule_cmd route_match_community_cmd = {
        "community", route_match_community, route_match_community_compile,
-       route_match_community_free};
+       route_match_community_free, route_match_get_community_key};
 
 /* Match function for lcommunity match. */
 static enum route_map_cmd_result_t
@@ -1281,7 +1300,8 @@ static void route_match_lcommunity_free(void *rule)
 /* Route map commands for community matching. */
 struct route_map_rule_cmd route_match_lcommunity_cmd = {
        "large-community", route_match_lcommunity,
-       route_match_lcommunity_compile, route_match_lcommunity_free};
+       route_match_lcommunity_compile, route_match_lcommunity_free,
+       route_match_get_community_key};
 
 
 /* Match function for extcommunity match. */
@@ -2728,10 +2748,8 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
                path = object;
                peer = path->peer;
 
-               if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
-                    || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
-                   && peer->su_remote
-                   && sockunion_family(peer->su_remote) == AF_INET6) {
+               if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
+                   || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
                        /* Set next hop preference to global */
                        path->attr->mp_nexthop_prefer_global = true;
                        SET_FLAG(path->attr->rmap_change_flags,
@@ -2853,12 +2871,15 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx,
                        /* Set next hop value and length in attribute. */
                        if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
                                path->attr->mp_nexthop_local = peer_address;
-                               if (path->attr->mp_nexthop_len != 32)
-                                       path->attr->mp_nexthop_len = 32;
+                               if (path->attr->mp_nexthop_len
+                                   != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+                                       path->attr->mp_nexthop_len =
+                                               BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
                        } else {
                                path->attr->mp_nexthop_global = peer_address;
                                if (path->attr->mp_nexthop_len == 0)
-                                       path->attr->mp_nexthop_len = 16;
+                                       path->attr->mp_nexthop_len =
+                                               BGP_ATTR_NHLEN_IPV6_GLOBAL;
                        }
 
                } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
@@ -2923,7 +2944,7 @@ route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix,
 
                /* Set next hop value. */
                path->attr->mp_nexthop_global_in = *address;
-               path->attr->mp_nexthop_len = 4;
+               path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
        }
 
        return RMAP_OKAY;
@@ -3057,7 +3078,7 @@ static int bgp_route_match_add(struct vty *vty, const char *command,
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
        int retval = CMD_SUCCESS;
-       int ret;
+       enum rmap_compile_rets ret;
 
        ret = route_map_add_match(index, command, arg, type);
        switch (ret) {
@@ -3070,9 +3091,9 @@ static int bgp_route_match_add(struct vty *vty, const char *command,
                retval = CMD_WARNING_CONFIG_FAILED;
                break;
        case RMAP_COMPILE_SUCCESS:
-               if (type != RMAP_EVENT_MATCH_ADDED) {
-                       route_map_upd8_dependency(type, arg, index->map->name);
-               }
+               /*
+                * Intentionally doing nothing here.
+                */
                break;
        }
 
@@ -3084,7 +3105,7 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
                                  const char *arg, route_map_event_t type)
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
-       int ret;
+       enum rmap_compile_rets ret;
        int retval = CMD_SUCCESS;
        char *dep_name = NULL;
        const char *tmpstr;
@@ -3103,7 +3124,7 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
                rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
        }
 
-       ret = route_map_delete_match(index, command, dep_name);
+       ret = route_map_delete_match(index, command, dep_name, type);
        switch (ret) {
        case RMAP_RULE_MISSING:
                vty_out(vty, "%% BGP Can't find rule.\n");
@@ -3114,8 +3135,9 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
                retval = CMD_WARNING_CONFIG_FAILED;
                break;
        case RMAP_COMPILE_SUCCESS:
-               if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
-                       route_map_upd8_dependency(type, dep_name, rmap_name);
+               /*
+                * Nothing to do here
+                */
                break;
        }
 
@@ -3238,6 +3260,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
        struct peer *peer;
        struct bgp_node *bn;
        struct bgp_static *bgp_static;
+       struct bgp_aggregate *aggregate;
        struct listnode *node, *nnode;
        struct route_map *map;
        char buf[INET6_ADDRSTRLEN];
@@ -3321,6 +3344,35 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                                  safi);
                        }
                }
+
+               /* For aggregate-address route-map updates. */
+               for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
+                    bn = bgp_route_next(bn)) {
+                       aggregate = bgp_node_get_bgp_aggregate_info(bn);
+                       if (!aggregate)
+                               continue;
+
+                       if (!aggregate->rmap.name
+                           || (strcmp(rmap_name, aggregate->rmap.name) != 0))
+                               continue;
+
+                       if (!aggregate->rmap.map)
+                               route_map_counter_increment(map);
+
+                       aggregate->rmap.map = map;
+
+                       if (route_update) {
+                               if (bgp_debug_zebra(&bn->p))
+                                       zlog_debug(
+                                               "Processing route_map %s update on aggregate-address route %s",
+                                               rmap_name,
+                                               inet_ntop(bn->p.family,
+                                                         &bn->p.u.prefix, buf,
+                                                         INET6_ADDRSTRLEN));
+                               bgp_aggregate_route(bgp, &bn->p, afi, safi,
+                                                   aggregate);
+                       }
+               }
        }
 
        /* For redistribute route-map updates. */
@@ -4158,6 +4210,18 @@ DEFUN (no_set_aspath_prepend,
        return ret;
 }
 
+DEFUN (no_set_aspath_prepend_lastas,
+       no_set_aspath_prepend_lastas_cmd,
+       "no set as-path prepend last-as [(1-10)]",
+       NO_STR
+       SET_STR
+       "Transform BGP AS_PATH attribute\n"
+       "Prepend to the as-path\n"
+       "Use the peers AS-number\n"
+       "Number of times to insert\n")
+{
+       return no_set_aspath_prepend(self, vty, argc, argv);
+}
 
 DEFUN (set_aspath_exclude,
        set_aspath_exclude_cmd,
@@ -5123,6 +5187,7 @@ void bgp_route_map_init(void)
        install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
        install_element(RMAP_NODE, &set_aspath_exclude_cmd);
        install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
+       install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
        install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
        install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
        install_element(RMAP_NODE, &set_origin_cmd);