#include "bgpd/bgp_filter.h"
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_lcommunity.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_debug.h"
as-path tag : Not yet
automatic-tag : (This will not be implemented by bgpd)
community : Done
+ large-community : Done
+ large-comm-list : Done
comm-list : Not yet
dampning : Not yet
default : (This will not be implemented by bgpd)
route_match_community_free
};
+/* Match function for lcommunity match. */
+static route_map_result_t
+route_match_lcommunity (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct community_list *list;
+ struct bgp_info *bgp_info;
+ struct rmap_community *rcom;
+
+ if (type == RMAP_BGP)
+ {
+ bgp_info = object;
+ rcom = rule;
+
+ list = community_list_lookup (bgp_clist, rcom->name,
+ LARGE_COMMUNITY_LIST_MASTER);
+ if (! list)
+ return RMAP_NOMATCH;
+
+ if (bgp_info->attr->extra &&
+ lcommunity_list_match (bgp_info->attr->extra->lcommunity, list))
+ return RMAP_MATCH;
+
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Compile function for community match. */
+static void *
+route_match_lcommunity_compile (const char *arg)
+{
+ struct rmap_community *rcom;
+ int len;
+ char *p;
+
+ rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
+
+ p = strchr (arg, ' ');
+ if (p)
+ {
+ len = p - arg;
+ rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+ memcpy (rcom->name, arg, len);
+ }
+ else
+ {
+ rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+ rcom->exact = 0;
+ }
+ return rcom;
+}
+
+/* Compile function for community match. */
+static void
+route_match_lcommunity_free (void *rule)
+{
+ struct rmap_community *rcom = rule;
+
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name);
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
+}
+
+/* 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
+};
+
+
/* Match function for extcommunity match. */
static route_map_result_t
route_match_ecommunity (void *rule, struct prefix *prefix,
route_set_community_free,
};
+/* `set community COMMUNITY' */
+struct rmap_lcom_set
+{
+ struct lcommunity *lcom;
+ int additive;
+ int none;
+};
+
+
+/* For lcommunity set mechanism. */
+static route_map_result_t
+route_set_lcommunity (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct rmap_lcom_set *rcs;
+ struct bgp_info *binfo;
+ struct attr *attr;
+ struct lcommunity *new = NULL;
+ struct lcommunity *old;
+ struct lcommunity *merge;
+
+ if (type == RMAP_BGP)
+ {
+ rcs = rule;
+ binfo = object;
+ attr = binfo->attr;
+ old = (attr->extra) ? attr->extra->lcommunity : NULL;
+
+ /* "none" case. */
+ if (rcs->none)
+ {
+ attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
+ if (attr->extra)
+ attr->extra->lcommunity = NULL;
+
+ /* See the longer comment down below. */
+ if (old && old->refcnt == 0)
+ lcommunity_free(&old);
+ return RMAP_OKAY;
+ }
+
+ if (rcs->additive && old)
+ {
+ merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom);
+
+ /* HACK: if the old large-community is not intern'd,
+ * we should free it here, or all reference to it may be lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old->refcnt == 0)
+ lcommunity_free (&old);
+ new = lcommunity_uniq_sort (merge);
+ lcommunity_free (&merge);
+ }
+ else
+ new = lcommunity_dup (rcs->lcom);
+
+ /* will be intern()'d or attr_flush()'d by bgp_update_main() */
+ (bgp_attr_extra_get (attr))->lcommunity = new;
+
+ attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+static void *
+route_set_lcommunity_compile (const char *arg)
+{
+ struct rmap_lcom_set *rcs;
+ struct lcommunity *lcom = NULL;
+ char *sp;
+ int additive = 0;
+ int none = 0;
+
+ if (strcmp (arg, "none") == 0)
+ none = 1;
+ else
+ {
+ sp = strstr (arg, "additive");
+
+ if (sp && sp > arg)
+ {
+ /* "additive" keyworkd is included. */
+ additive = 1;
+ *(sp - 1) = '\0';
+ }
+
+ lcom = lcommunity_str2com (arg);
+
+ if (additive)
+ *(sp - 1) = ' ';
+
+ if (! lcom)
+ return NULL;
+ }
+
+ rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
+ rcs->lcom = lcom;
+ rcs->additive = additive;
+ rcs->none = none;
+
+ return rcs;
+}
+
+/* Free function for set lcommunity. */
+static void
+route_set_lcommunity_free (void *rule)
+{
+ struct rmap_lcom_set *rcs = rule;
+
+ if (rcs->lcom) {
+ lcommunity_free (&rcs->lcom);
+ }
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_lcommunity_cmd =
+{
+ "large-community",
+ route_set_lcommunity,
+ route_set_lcommunity_compile,
+ route_set_lcommunity_free,
+};
+
+/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
+
+/* For large community set mechanism. */
+static route_map_result_t
+route_set_lcommunity_delete (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct community_list *list;
+ struct lcommunity *merge;
+ struct lcommunity *new;
+ struct lcommunity *old;
+ struct bgp_info *binfo;
+
+ if (type == RMAP_BGP)
+ {
+ if (! rule)
+ return RMAP_OKAY;
+
+ binfo = object;
+ list = community_list_lookup (bgp_clist, rule,
+ LARGE_COMMUNITY_LIST_MASTER);
+ old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL);
+
+ if (list && old)
+ {
+ merge = lcommunity_list_match_delete (lcommunity_dup (old), list);
+ new = lcommunity_uniq_sort (merge);
+ lcommunity_free (&merge);
+
+ /* HACK: if the old community is not intern'd,
+ * we should free it here, or all reference to it may be lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old->refcnt == 0)
+ lcommunity_free (&old);
+
+ if (new->size == 0)
+ {
+ binfo->attr->extra->lcommunity = NULL;
+ binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+ lcommunity_free (&new);
+ }
+ else
+ {
+ binfo->attr->extra->lcommunity = new;
+ binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+ }
+ }
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Compile function for set lcommunity. */
+static void *
+route_set_lcommunity_delete_compile (const char *arg)
+{
+ char *p;
+ char *str;
+ int len;
+
+ p = strchr (arg, ' ');
+ if (p)
+ {
+ len = p - arg;
+ str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+ memcpy (str, arg, len);
+ }
+ else
+ str = NULL;
+
+ return str;
+}
+
+/* Free function for set lcommunity. */
+static void
+route_set_lcommunity_delete_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set lcommunity rule structure. */
+struct route_map_rule_cmd route_set_lcommunity_delete_cmd =
+{
+ "large-comm-list",
+ route_set_lcommunity_delete,
+ route_set_lcommunity_delete_compile,
+ route_set_lcommunity_delete_free,
+};
+
+
/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
/* For community set mechanism. */
};
-#ifdef HAVE_IPV6
/* `match ipv6 address IP_ACCESS_LIST' */
static route_map_result_t
route_set_ipv6_nexthop_peer_free
};
-#endif /* HAVE_IPV6 */
-
-/* `set vpnv4 nexthop A.B.C.D' */
+/* `set ip vpn nexthop A.B.C.D' */
static route_map_result_t
route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
return address;
}
+/* `set ipv6 vpn nexthop A.B.C.D' */
+
+static route_map_result_t
+route_set_vpnv6_nexthop (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct in6_addr *address;
+ struct bgp_info *bgp_info;
+
+ if (type == RMAP_BGP)
+ {
+ /* Fetch routemap's rule information. */
+ address = rule;
+ bgp_info = object;
+
+ /* Set next hop value. */
+ memcpy (&(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global, address, sizeof(struct in6_addr));
+ (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
+ }
+
+ return RMAP_OKAY;
+}
+
+static void *
+route_set_vpnv6_nexthop_compile (const char *arg)
+{
+ int ret;
+ struct in6_addr *address;
+
+ address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+ ret = inet_pton (AF_INET6, arg, address);
+
+ if (ret == 0)
+ {
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+ return NULL;
+ }
+
+ return address;
+}
+
static void
-route_set_vpnv4_nexthop_free (void *rule)
+route_set_vpn_nexthop_free (void *rule)
{
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for ip nexthop set. */
struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
{
- "vpnv4 next-hop",
+ "ip vpn next-hop",
route_set_vpnv4_nexthop,
route_set_vpnv4_nexthop_compile,
- route_set_vpnv4_nexthop_free
+ route_set_vpn_nexthop_free
+};
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd =
+{
+ "ipv6 vpn next-hop",
+ route_set_vpnv6_nexthop,
+ route_set_vpnv6_nexthop_compile,
+ route_set_vpn_nexthop_free
};
/* `set originator-id' */
/* Add bgp route map rule. */
static int
-bgp_route_match_add (struct vty *vty, struct route_map_index *index,
+bgp_route_match_add (struct vty *vty,
const char *command, const char *arg,
route_map_event_t type)
{
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
int ret;
ret = route_map_add_match (index, command, arg);
/* Delete bgp route map rule. */
static int
-bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
+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;
char *dep_name = NULL;
const char *tmpstr;
"IPv6 address of peer\n")
{
int idx_ip = 2;
- return bgp_route_match_add (vty, vty->index, "peer", argv[idx_ip]->arg,
+ return bgp_route_match_add (vty, "peer", argv[idx_ip]->arg,
RMAP_EVENT_MATCH_ADDED);
}
"Match peer address\n"
"Static or Redistributed routes\n")
{
- return bgp_route_match_add (vty, vty->index, "peer", "local",
+ return bgp_route_match_add (vty, "peer", "local",
RMAP_EVENT_MATCH_DELETED);
}
int idx_peer = 3;
if (argc <= idx_peer)
- return bgp_route_match_delete (vty, vty->index, "peer", NULL,
+ return bgp_route_match_delete (vty, "peer", NULL,
RMAP_EVENT_MATCH_DELETED);
- return bgp_route_match_delete (vty, vty->index, "peer", argv[idx_peer]->arg,
+ return bgp_route_match_delete (vty, "peer", argv[idx_peer]->arg,
RMAP_EVENT_MATCH_DELETED);
}
"Percentage of routes\n")
{
int idx_number = 2;
- return bgp_route_match_add (vty, vty->index, "probability", argv[idx_number]->arg,
+ return bgp_route_match_add (vty, "probability", argv[idx_number]->arg,
RMAP_EVENT_MATCH_ADDED);
}
{
int idx_number = 3;
if (argc <= idx_number)
- return bgp_route_match_delete (vty, vty->index, "probability", NULL,
+ return bgp_route_match_delete (vty, "probability", NULL,
RMAP_EVENT_MATCH_DELETED);
- return bgp_route_match_delete (vty, vty->index, "probability", argv[idx_number]->arg,
+ return bgp_route_match_delete (vty, "probability", argv[idx_number]->arg,
RMAP_EVENT_MATCH_DELETED);
}
"IP standard access-list name\n")
{
int idx_acl = 3;
- return bgp_route_match_add (vty, vty->index, "ip route-source", argv[idx_acl]->arg,
+ return bgp_route_match_add (vty, "ip route-source", argv[idx_acl]->arg,
RMAP_EVENT_FILTER_ADDED);
}
{
int idx_number = 4;
if (argc <= idx_number)
- return bgp_route_match_delete (vty, vty->index, "ip route-source",
+ return bgp_route_match_delete (vty, "ip route-source",
NULL, RMAP_EVENT_FILTER_DELETED);
- return bgp_route_match_delete (vty, vty->index, "ip route-source",
+ return bgp_route_match_delete (vty, "ip route-source",
argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED);
}
"IP prefix-list name\n")
{
int idx_word = 4;
- return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list",
+ return bgp_route_match_add (vty, "ip route-source prefix-list",
argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
}
{
int idx_word = 5;
if (argc <= idx_word)
- return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
+ return bgp_route_match_delete (vty, "ip route-source prefix-list",
NULL, RMAP_EVENT_PLIST_DELETED);
- return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
+ return bgp_route_match_delete (vty, "ip route-source prefix-list",
argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
}
"Metric value\n")
{
int idx_number = 2;
- return bgp_route_match_add (vty, vty->index, "local-preference", argv[idx_number]->arg,
+ return bgp_route_match_add (vty, "local-preference", argv[idx_number]->arg,
RMAP_EVENT_MATCH_ADDED);
}
{
int idx_localpref = 3;
if (argc <= idx_localpref)
- return bgp_route_match_delete (vty, vty->index, "local-preference",
+ return bgp_route_match_delete (vty, "local-preference",
NULL, RMAP_EVENT_MATCH_DELETED);
- return bgp_route_match_delete (vty, vty->index, "local-preference",
+ return bgp_route_match_delete (vty, "local-preference",
argv[idx_localpref]->arg,
RMAP_EVENT_MATCH_DELETED);
}
DEFUN (match_community,
match_community_cmd,
- "match community <(1-99)|(100-500)|WORD>",
- MATCH_STR
- "Match BGP community list\n"
- "Community-list number (standard)\n"
- "Community-list number (expanded)\n"
- "Community-list name\n")
-{
- int idx_comm_list = 2;
- return bgp_route_match_add (vty, vty->index, "community", argv[idx_comm_list]->arg,
- RMAP_EVENT_CLIST_ADDED);
-}
-
-DEFUN (match_community_exact,
- match_community_exact_cmd,
- "match community <(1-99)|(100-500)|WORD> exact-match",
+ "match community <(1-99)|(100-500)|WORD> [exact-match]",
MATCH_STR
"Match BGP community list\n"
"Community-list number (standard)\n"
int ret;
char *argstr;
- argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
- strlen (argv[idx_comm_list]->arg) + strlen ("exact-match") + 2);
+ if (argc == 4)
+ {
+ argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+ strlen (argv[idx_comm_list]->arg) +
+ strlen ("exact-match") + 2);
- sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
+ sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
+ }
+ else
+ argstr = argv[idx_comm_list]->arg;
- ret = bgp_route_match_add (vty, vty->index, "community", argstr,
+ ret = bgp_route_match_add (vty, "community", argstr,
RMAP_EVENT_CLIST_ADDED);
- XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+ if (argstr != argv[idx_comm_list]->arg)
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
return ret;
}
"Community-list name\n"
"Do exact matching of communities\n")
{
- return bgp_route_match_delete (vty, vty->index, "community", NULL,
+ return bgp_route_match_delete (vty, "community", NULL,
RMAP_EVENT_CLIST_DELETED);
}
+DEFUN (match_lcommunity,
+ match_lcommunity_cmd,
+ "match large-community <(1-99)|(100-500)|WORD>",
+ MATCH_STR
+ "Match BGP large community list\n"
+ "Large Community-list number (standard)\n"
+ "Large Community-list number (expanded)\n"
+ "Large Community-list name\n")
+{
+ return bgp_route_match_add (vty, "large-community", argv[2]->arg,
+ RMAP_EVENT_LLIST_ADDED);
+}
+DEFUN (no_match_lcommunity,
+ no_match_lcommunity_cmd,
+ "no match large-community [<(1-99)|(100-500)|WORD>]",
+ NO_STR
+ MATCH_STR
+ "Match BGP large community list\n"
+ "Large Community-list number (standard)\n"
+ "Large Community-list number (expanded)\n"
+ "Large Community-list name\n")
+{
+ return bgp_route_match_delete (vty, "large-community", NULL,
+ RMAP_EVENT_LLIST_DELETED);
+}
DEFUN (match_ecommunity,
match_ecommunity_cmd,
"Extended community-list name\n")
{
int idx_comm_list = 2;
- return bgp_route_match_add (vty, vty->index, "extcommunity", argv[idx_comm_list]->arg,
+ return bgp_route_match_add (vty, "extcommunity", argv[idx_comm_list]->arg,
RMAP_EVENT_ECLIST_ADDED);
}
"Extended community-list number (expanded)\n"
"Extended community-list name\n")
{
- return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL,
+ return bgp_route_match_delete (vty, "extcommunity", NULL,
RMAP_EVENT_ECLIST_DELETED);
}
"AS path access-list name\n")
{
int idx_word = 2;
- return bgp_route_match_add (vty, vty->index, "as-path", argv[idx_word]->arg,
+ return bgp_route_match_add (vty, "as-path", argv[idx_word]->arg,
RMAP_EVENT_ASLIST_ADDED);
}
"Match BGP AS path list\n"
"AS path access-list name\n")
{
- return bgp_route_match_delete (vty, vty->index, "as-path", NULL,
+ return bgp_route_match_delete (vty, "as-path", NULL,
RMAP_EVENT_ASLIST_DELETED);
}
{
int idx_origin = 2;
if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "igp",
+ return bgp_route_match_add (vty, "origin", "igp",
RMAP_EVENT_MATCH_ADDED);
if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "egp",
+ return bgp_route_match_add (vty, "origin", "egp",
RMAP_EVENT_MATCH_ADDED);
if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
- return bgp_route_match_add (vty, vty->index, "origin", "incomplete",
+ return bgp_route_match_add (vty, "origin", "incomplete",
RMAP_EVENT_MATCH_ADDED);
return CMD_WARNING;
"local IGP\n"
"unknown heritage\n")
{
- return bgp_route_match_delete (vty, vty->index, "origin", NULL,
+ return bgp_route_match_delete (vty, "origin", NULL,
RMAP_EVENT_MATCH_DELETED);
}
"Next hop address\n"
"Use peer address (for BGP only)\n")
{
- return generic_set_add (vty, vty->index, "ip next-hop", "peer-address");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip next-hop", "peer-address");
}
DEFUN (set_ip_nexthop_unchanged,
"Next hop address\n"
"Don't modify existing Next hop address\n")
{
- return generic_set_add (vty, vty->index, "ip next-hop", "unchanged");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip next-hop", "unchanged");
}
"Preference value\n")
{
int idx_number = 2;
- return generic_set_add (vty, vty->index, "local-preference", argv[idx_number]->arg);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "local-preference", argv[idx_number]->arg);
}
{
int idx_localpref = 3;
if (argc <= idx_localpref)
- return generic_set_delete (vty, vty->index, "local-preference", NULL);
- return generic_set_delete (vty, vty->index, "local-preference", argv[idx_localpref]->arg);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "local-preference", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "local-preference", argv[idx_localpref]->arg);
}
"Weight value\n")
{
int idx_number = 2;
- return generic_set_add (vty, vty->index, "weight", argv[idx_number]->arg);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "weight",
+ argv[idx_number]->arg);
}
{
int idx_weight = 3;
if (argc <= idx_weight)
- return generic_set_delete (vty, vty->index, "weight", NULL);
- return generic_set_delete (vty, vty->index, "weight", argv[idx_weight]->arg);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "weight", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "weight",
+ argv[idx_weight]->arg);
}
char *str;
str = argv_concat (argv, argc, idx_asn);
- ret = generic_set_add (vty, vty->index, "as-path prepend", str);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "as-path prepend", str);
XFREE (MTYPE_TMP, str);
return ret;
DEFUN (set_aspath_prepend_lastas,
set_aspath_prepend_lastas_cmd,
- "set as-path prepend last-as (1-10)",
+ "set as-path prepend last-as (1-9)",
SET_STR
"Transform BGP AS_PATH attribute\n"
"Prepend to the as-path\n"
char *str;
str = argv_concat (argv, argc, idx_asn);
- ret = generic_set_delete (vty, vty->index, "as-path prepend", str);
+ ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "as-path prepend", str);
XFREE (MTYPE_TMP, str);
return ret;
}
char *str;
str = argv_concat (argv, argc, idx_asn);
- ret = generic_set_add (vty, vty->index, "as-path exclude", str);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "as-path exclude", str);
XFREE (MTYPE_TMP, str);
return ret;
}
char *str;
str = argv_concat (argv, argc, idx_asn);
- ret = generic_set_delete (vty, vty->index, "as-path exclude", str);
+ ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "as-path exclude", str);
XFREE (MTYPE_TMP, str);
return ret;
}
argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
strcpy (argstr, str);
strcpy (argstr + strlen (str), " additive");
- ret = generic_set_add (vty, vty->index, "community", argstr);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "community", argstr);
XFREE (MTYPE_TMP, argstr);
}
else
- ret = generic_set_add (vty, vty->index, "community", str);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "community", str);
community_free (com);
"BGP community attribute\n"
"No community attribute\n")
{
- return generic_set_add (vty, vty->index, "community", "none");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community",
+ "none");
}
DEFUN (no_set_community,
"BGP community attribute\n"
COMMUNITY_VAL_STR)
{
- return generic_set_delete (vty, vty->index, "community", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "community", NULL);
}
strcpy (str, argv[idx_comm_list]->arg);
strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
- generic_set_add (vty, vty->index, "comm-list", str);
+ generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "comm-list", str);
XFREE (MTYPE_TMP, str);
return CMD_SUCCESS;
"Community-list name\n"
"Delete matching communities\n")
{
- return generic_set_delete (vty, vty->index, "comm-list", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "comm-list", NULL);
+}
+
+DEFUN (set_lcommunity,
+ set_lcommunity_cmd,
+ "set large-community AA:BB:CC...",
+ SET_STR
+ "BGP large community attribute\n"
+ "Large Community number in aa:bb:cc format or additive\n")
+{
+ int ret;
+ char *str;
+
+ str = argv_concat (argv, argc, 2);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "large-community", str);
+ XFREE (MTYPE_TMP, str);
+
+ return ret;
+}
+
+DEFUN (set_lcommunity_none,
+ set_lcommunity_none_cmd,
+ "set large-community none",
+ SET_STR
+ "BGP large community attribute\n"
+ "No large community attribute\n")
+{
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "large-community", "none");
+}
+
+DEFUN (no_set_lcommunity,
+ no_set_lcommunity_cmd,
+ "no set large-community none",
+ NO_STR
+ SET_STR
+ "BGP large community attribute\n"
+ "No community attribute\n")
+{
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "large-community", NULL);
+}
+
+DEFUN (no_set_lcommunity1,
+ no_set_lcommunity1_cmd,
+ "no set large-community AA:BB:CC...",
+ NO_STR
+ SET_STR
+ "BGP large community attribute\n"
+ "Large community in AA:BB:CC... format or additive\n")
+{
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "large-community", NULL);
}
+DEFUN (set_lcommunity_delete,
+ set_lcommunity_delete_cmd,
+ "set large-comm-list <(1-99)|(100-500)|WORD> delete",
+ SET_STR
+ "set BGP large community list (for deletion)\n"
+ "Large Community-list number (standard)\n"
+ "Large Communitly-list number (expanded)\n"
+ "Large Community-list name\n"
+ "Delete matching large communities\n")
+{
+ char *str;
+
+ str = XCALLOC (MTYPE_TMP, strlen (argv[2]->arg) + strlen (" delete") + 1);
+ strcpy (str, argv[2]->arg);
+ strcpy (str + strlen (argv[2]->arg), " delete");
+
+ generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "large-comm-list", str);
+
+ XFREE (MTYPE_TMP, str);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_set_lcommunity_delete,
+ no_set_lcommunity_delete_cmd,
+ "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
+ NO_STR
+ SET_STR
+ "set BGP large community list (for deletion)\n"
+ "Large Community-list number (standard)\n"
+ "Large Communitly-list number (expanded)\n"
+ "Large Community-list name\n"
+ "Delete matching large communities\n")
+{
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "large-comm-list", NULL);
+}
DEFUN (set_ecommunity_rt,
set_ecommunity_rt_cmd,
char *str;
str = argv_concat (argv, argc, idx_asn_nn);
- ret = generic_set_add (vty, vty->index, "extcommunity rt", str);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity rt", str);
XFREE (MTYPE_TMP, str);
return ret;
"Route Target extended community\n"
"VPN extended community\n")
{
- return generic_set_delete (vty, vty->index, "extcommunity rt", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity rt", NULL);
}
char *str;
str = argv_concat (argv, argc, idx_asn_nn);
- ret = generic_set_add (vty, vty->index, "extcommunity soo", str);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity soo", str);
XFREE (MTYPE_TMP, str);
return ret;
}
"Site-of-Origin extended community\n"
"VPN extended community\n")
{
- return generic_set_delete (vty, vty->index, "extcommunity soo", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "extcommunity soo", NULL);
}
{
int idx_origin = 2;
if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
- return generic_set_add (vty, vty->index, "origin", "igp");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+ "igp");
if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
- return generic_set_add (vty, vty->index, "origin", "egp");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+ "egp");
if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
- return generic_set_add (vty, vty->index, "origin", "incomplete");
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+ "incomplete");
return CMD_WARNING;
}
"local IGP\n"
"unknown heritage\n")
{
- return generic_set_delete (vty, vty->index, "origin", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+ NULL);
}
SET_STR
"BGP atomic aggregate attribute\n" )
{
- return generic_set_add (vty, vty->index, "atomic-aggregate", NULL);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "atomic-aggregate", NULL);
}
DEFUN (no_set_atomic_aggregate,
SET_STR
"BGP atomic aggregate attribute\n" )
{
- return generic_set_delete (vty, vty->index, "atomic-aggregate", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "atomic-aggregate", NULL);
}
DEFUN (set_aggregator_as,
sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
- ret = generic_set_add (vty, vty->index, "aggregator as", argstr);
+ ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "aggregator as", argstr);
XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
char *argstr;
if (argc <= idx_asn)
- return generic_set_delete (vty, vty->index, "aggregator as", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "aggregator as", NULL);
ret = inet_aton (argv[idx_ip]->arg, &address);
if (ret == 0)
sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
- ret = generic_set_delete (vty, vty->index, "aggregator as", argstr);
+ ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "aggregator as", argstr);
XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
return ret;
}
-#ifdef HAVE_IPV6
DEFUN (match_ipv6_next_hop,
match_ipv6_next_hop_cmd,
"match ipv6 next-hop X:X::X:X",
"IPv6 address of next hop\n")
{
int idx_ipv6 = 3;
- return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
+ return bgp_route_match_add (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
RMAP_EVENT_MATCH_ADDED);
}
"IPv6 address of next hop\n")
{
int idx_ipv6 = 4;
- return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
+ return bgp_route_match_delete (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
RMAP_EVENT_MATCH_DELETED);
}
"Next hop address\n"
"Use peer address (for BGP only)\n")
{
- return generic_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop peer-address", NULL);
}
DEFUN (no_set_ipv6_nexthop_peer,
"IPv6 next-hop address\n"
"Use peer address (for BGP only)\n")
{
- return generic_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop peer-address", NULL);
}
DEFUN (set_ipv6_nexthop_prefer_global,
"IPv6 next-hop address\n"
"Prefer global over link-local if both exist\n")
{
- return generic_set_add (vty, vty->index, "ipv6 next-hop prefer-global", NULL);;
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop prefer-global", NULL);;
}
DEFUN (no_set_ipv6_nexthop_prefer_global,
"IPv6 next-hop address\n"
"Prefer global over link-local if both exist\n")
{
- return generic_set_delete (vty, vty->index, "ipv6 next-hop prefer-global", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop prefer-global", NULL);
}
DEFUN (set_ipv6_nexthop_global,
return CMD_WARNING;
}
- return generic_set_add (vty, vty->index, "ipv6 next-hop global", argv[idx_ipv6]->arg);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop global", argv[idx_ipv6]->arg);
}
{
int idx_ipv6 = 5;
if (argc <= idx_ipv6)
- return generic_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
- return generic_set_delete (vty, vty->index, "ipv6 next-hop global", argv[idx_ipv6]->arg);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop global", NULL);
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 next-hop global", argv[idx_ipv6]->arg);
}
-#endif /* HAVE_IPV6 */
-DEFUN (set_vpnv4_nexthop,
- set_vpnv4_nexthop_cmd,
- "set vpnv4 next-hop A.B.C.D",
+#ifdef KEEP_OLD_VPN_COMMANDS
+DEFUN (set_vpn_nexthop,
+ set_vpn_nexthop_cmd,
+ "set <vpnv4|vpnv6> next-hop [A.B.C.D|X:X::X:X]",
SET_STR
"VPNv4 information\n"
- "VPNv4 next-hop address\n"
- "IP address of next hop\n")
+ "VPNv6 information\n"
+ "VPN next-hop address\n"
+ "IP address of next hop\n"
+ "IPv6 address of next hop\n")
{
- int idx_ipv4 = 3;
- return generic_set_add (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
-}
+ int idx_ip = 3;
+ afi_t afi;
+ int idx = 0;
+ if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
+ {
+ if (afi == AFI_IP)
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip vpn next-hop", argv[idx_ip]->arg);
+ else
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 vpn next-hop", argv[idx_ip]->arg);
+ }
+ return CMD_SUCCESS;
+}
-DEFUN (no_set_vpnv4_nexthop,
- no_set_vpnv4_nexthop_cmd,
- "no set vpnv4 next-hop [A.B.C.D]",
+DEFUN (no_set_vpn_nexthop,
+ no_set_vpn_nexthop_cmd,
+ "no set vpn next-hop [A.B.C.D|X:X::X:X]",
NO_STR
SET_STR
- "VPNv4 information\n"
- "VPNv4 next-hop address\n"
- "IP address of next hop\n")
+ "VPN information\n"
+ "VPN next-hop address\n"
+ "IP address of next hop\n"
+ "IPv6 address of next hop\n")
{
- int idx_ipv4 = 4;
- if (argc <= idx_ipv4)
- return generic_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
- return generic_set_delete (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
+ int idx_ip = 4;
+ char *arg;
+ afi_t afi;
+ int idx = 0;
+
+ if (argc <= idx_ip)
+ arg = NULL;
+ else
+ arg = argv[idx_ip]->arg;
+ if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
+ {
+ if (afi == AFI_IP)
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip vpn next-hop", arg);
+ else
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 vpn next-hop", argv[idx_ip]->arg);
+ }
+ return CMD_SUCCESS;
+}
+#endif /* KEEP_OLD_VPN_COMMANDS */
+
+DEFUN (set_ipx_vpn_nexthop,
+ set_ipx_vpn_nexthop_cmd,
+ "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
+ SET_STR
+ "IPv4 information\n"
+ "IPv6 information\n"
+ "VPN information\n"
+ "VPN next-hop address\n"
+ "IP address of next hop\n"
+ "IPv6 address of next hop\n")
+{
+ int idx_ip = 4;
+ afi_t afi;
+ int idx = 0;
+
+ if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
+ {
+ if (afi == AFI_IP)
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip vpn next-hop", argv[idx_ip]->arg);
+ else
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 vpn next-hop", argv[idx_ip]->arg);
+ }
+ return CMD_SUCCESS;
}
+DEFUN (no_set_ipx_vpn_nexthop,
+ no_set_ipx_vpn_nexthop_cmd,
+ "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
+ NO_STR
+ SET_STR
+ "IPv4 information\n"
+ "IPv6 information\n"
+ "VPN information\n"
+ "VPN next-hop address\n"
+ "IP address of next hop\n"
+ "IPv6 address of next hop\n")
+{
+ int idx_ip = 5;
+ char *arg;
+ afi_t afi;
+ int idx = 0;
+
+ if (argc <= idx_ip)
+ arg = NULL;
+ else
+ arg = argv[idx_ip]->arg;
+ if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
+ {
+ if (afi == AFI_IP)
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ip vpn next-hop", arg);
+ else
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "ipv6 vpn next-hop", argv[idx_ip]->arg);
+ }
+ return CMD_SUCCESS;
+}
DEFUN (set_originator_id,
set_originator_id_cmd,
"IP address of originator\n")
{
int idx_ipv4 = 2;
- return generic_set_add (vty, vty->index, "originator-id", argv[idx_ipv4]->arg);
+ return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+ "originator-id", argv[idx_ipv4]->arg);
}
"BGP originator ID attribute\n"
"IP address of originator\n")
{
- int idx_id = 3;
- if (argc < idx_id)
- return generic_set_delete (vty, vty->index, "originator-id", NULL);
- return generic_set_delete (vty, vty->index, "originator-id", argv[idx_id]->arg);
+ int idx = 0;
+ char *arg = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
+
+ return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+ "originator-id", arg);
}
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);
+ route_map_install_match (&route_match_lcommunity_cmd);
route_map_install_match (&route_match_ecommunity_cmd);
route_map_install_match (&route_match_local_pref_cmd);
route_map_install_match (&route_match_metric_cmd);
route_map_install_set (&route_set_aggregator_as_cmd);
route_map_install_set (&route_set_community_cmd);
route_map_install_set (&route_set_community_delete_cmd);
+ route_map_install_set (&route_set_lcommunity_cmd);
+ route_map_install_set (&route_set_lcommunity_delete_cmd);
route_map_install_set (&route_set_vpnv4_nexthop_cmd);
+ route_map_install_set (&route_set_vpnv6_nexthop_cmd);
route_map_install_set (&route_set_originator_id_cmd);
route_map_install_set (&route_set_ecommunity_rt_cmd);
route_map_install_set (&route_set_ecommunity_soo_cmd);
install_element (RMAP_NODE, &match_local_pref_cmd);
install_element (RMAP_NODE, &no_match_local_pref_cmd);
install_element (RMAP_NODE, &match_community_cmd);
- install_element (RMAP_NODE, &match_community_exact_cmd);
install_element (RMAP_NODE, &no_match_community_cmd);
+ install_element (RMAP_NODE, &match_lcommunity_cmd);
+ install_element (RMAP_NODE, &no_match_lcommunity_cmd);
install_element (RMAP_NODE, &match_ecommunity_cmd);
install_element (RMAP_NODE, &no_match_ecommunity_cmd);
install_element (RMAP_NODE, &match_origin_cmd);
install_element (RMAP_NODE, &no_set_community_cmd);
install_element (RMAP_NODE, &set_community_delete_cmd);
install_element (RMAP_NODE, &no_set_community_delete_cmd);
+ install_element (RMAP_NODE, &set_lcommunity_cmd);
+ install_element (RMAP_NODE, &set_lcommunity_none_cmd);
+ install_element (RMAP_NODE, &no_set_lcommunity_cmd);
+ install_element (RMAP_NODE, &no_set_lcommunity1_cmd);
+ install_element (RMAP_NODE, &set_lcommunity_delete_cmd);
+ install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd);
install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
- install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
- install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
+#ifdef KEEP_OLD_VPN_COMMANDS
+ install_element (RMAP_NODE, &set_vpn_nexthop_cmd);
+ install_element (RMAP_NODE, &no_set_vpn_nexthop_cmd);
+#endif /* KEEP_OLD_VPN_COMMANDS */
+ install_element (RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
+ install_element (RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
install_element (RMAP_NODE, &set_originator_id_cmd);
install_element (RMAP_NODE, &no_set_originator_id_cmd);
-#ifdef HAVE_IPV6
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);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
-#endif /* HAVE_IPV6 */
}
void