summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c17
-rw-r--r--bgpd/bgp_nht.c2
-rw-r--r--bgpd/bgp_vty.c78
-rw-r--r--doc/Makefile.am7
-rw-r--r--doc/developer/.gitignore1
-rw-r--r--doc/developer/Makefile.am (renamed from doc/developer/Makefile.in)0
-rw-r--r--doc/manpages/.gitignore1
-rw-r--r--doc/manpages/Makefile.am (renamed from doc/manpages/Makefile.in)7
-rw-r--r--doc/user/.gitignore1
-rw-r--r--doc/user/Makefile.am (renamed from doc/user/Makefile.in)7
-rw-r--r--doc/user/routemap.rst12
-rw-r--r--ospf6d/ospf6_asbr.c113
-rw-r--r--ospf6d/ospf6_intra.c2
-rw-r--r--sharpd/sharp_main.c2
-rw-r--r--sharpd/sharp_vty.c17
-rw-r--r--sharpd/sharp_zebra.c6
-rw-r--r--sharpd/sharp_zebra.h4
-rw-r--r--tests/Makefile.am1
-rw-r--r--vtysh/vtysh.c78
-rw-r--r--vtysh/vtysh.h1
-rw-r--r--vtysh/vtysh_main.c11
-rw-r--r--zebra/redistribute.c4
-rw-r--r--zebra/rt_netlink.c15
-rw-r--r--zebra/zebra_rib.c2
-rw-r--r--zebra/zebra_routemap.c95
-rw-r--r--zebra/zebra_routemap.h16
26 files changed, 336 insertions, 164 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 74a4f66098..8394c3a7b7 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -327,6 +327,12 @@ static int evpn_route_target_cmp(struct ecommunity *ecom1,
return strcmp(ecom1->str, ecom2->str);
}
+static void evpn_xxport_delete_ecomm(void *val)
+{
+ struct ecommunity *ecomm = val;
+ ecommunity_free(&ecomm);
+}
+
/*
* Mask off global-admin field of specified extended community (RT),
* just retain the local-admin field.
@@ -3240,8 +3246,6 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
static void update_autort_vni(struct hash_backet *backet, struct bgp *bgp)
{
struct bgpevpn *vpn = backet->data;
- struct listnode *node, *nnode;
- struct ecommunity *ecom;
if (!vpn) {
zlog_warn("%s: VNI hash entry for VNI not found", __PRETTY_FUNCTION__);
@@ -3252,16 +3256,12 @@ static void update_autort_vni(struct hash_backet *backet, struct bgp *bgp)
if (is_vni_live(vpn))
bgp_evpn_uninstall_routes(bgp, vpn);
bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
- for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom))
- ecommunity_free(&ecom);
list_delete_all_node(vpn->import_rtl);
bgp_evpn_derive_auto_rt_import(bgp, vpn);
if (is_vni_live(vpn))
bgp_evpn_install_routes(bgp, vpn);
}
if (!is_export_rt_configured(vpn)) {
- for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
- ecommunity_free(&ecom);
list_delete_all_node(vpn->export_rtl);
bgp_evpn_derive_auto_rt_export(bgp, vpn);
if (is_vni_live(vpn))
@@ -4100,8 +4100,10 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
/* Initialize route-target import and export lists */
vpn->import_rtl = list_new();
vpn->import_rtl->cmp = (int (*)(void *, void *))evpn_route_target_cmp;
+ vpn->import_rtl->del = evpn_xxport_delete_ecomm;
vpn->export_rtl = list_new();
vpn->export_rtl->cmp = (int (*)(void *, void *))evpn_route_target_cmp;
+ vpn->export_rtl->del = evpn_xxport_delete_ecomm;
bf_assign_index(bm->rd_idspace, vpn->rd_id);
derive_rd_rt_for_vni(bgp, vpn);
@@ -4651,10 +4653,11 @@ void bgp_evpn_init(struct bgp *bgp)
bgp->vrf_import_rtl = list_new();
bgp->vrf_import_rtl->cmp =
(int (*)(void *, void *))evpn_route_target_cmp;
-
+ bgp->vrf_import_rtl->del = evpn_xxport_delete_ecomm;
bgp->vrf_export_rtl = list_new();
bgp->vrf_export_rtl->cmp =
(int (*)(void *, void *))evpn_route_target_cmp;
+ bgp->vrf_export_rtl->del = evpn_xxport_delete_ecomm;
bgp->l2vnis = list_new();
bgp->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
}
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 8b6ff3fa22..2c9e379299 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -88,7 +88,7 @@ int bgp_find_nexthop(struct bgp_info *path, int connected)
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
{
- if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
+ if (LIST_EMPTY(&(bnc->paths)) && bnc->nht_info) {
if (BGP_DEBUG(nht, NHT)) {
char buf[PREFIX2STR_BUFFER];
zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 35477ba164..f4f4e63264 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -553,39 +553,46 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
const char *arg)
{
int ret;
+ bool found = false;
struct peer *peer;
struct listnode *node, *nnode;
/* Clear all neighbors. */
/*
* Pass along pointer to next node to peer_clear() when walking all
- * nodes
- * on the BGP instance as that may get freed if it is a doppelganger
+ * nodes on the BGP instance as that may get freed if it is a
+ * doppelganger
*/
if (sort == clear_all) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (!peer->afc[afi][safi])
+ continue;
+
if (stype == BGP_CLEAR_SOFT_NONE)
ret = peer_clear(peer, &nnode);
- else if (peer->afc[afi][safi])
- ret = peer_clear_soft(peer, afi, safi, stype);
else
- ret = 0;
+ ret = peer_clear_soft(peer, afi, safi, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
}
/* This is to apply read-only mode on this clear. */
if (stype == BGP_CLEAR_SOFT_NONE)
bgp->update_delay_over = 0;
+ if (!found)
+ vty_out(vty, "%%BGP: No %s peer configured",
+ afi_safi_print(afi, safi));
+
return CMD_SUCCESS;
}
- /* Clear specified neighbors. */
+ /* Clear specified neighbor. */
if (sort == clear_peer) {
union sockunion su;
- int ret;
/* Make sockunion for lookup. */
ret = str2sockunion(arg, &su);
@@ -610,7 +617,9 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
}
}
- if (stype == BGP_CLEAR_SOFT_NONE)
+ if (!peer->afc[afi][safi])
+ ret = BGP_ERR_AF_UNCONFIGURED;
+ else if (stype == BGP_CLEAR_SOFT_NONE)
ret = peer_clear(peer, NULL);
else
ret = peer_clear_soft(peer, afi, safi, stype);
@@ -621,7 +630,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
return CMD_SUCCESS;
}
- /* Clear all peer-group members. */
+ /* Clear all neighbors belonging to a specific peer-group. */
if (sort == clear_group) {
struct peer_group *group;
@@ -632,27 +641,37 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
}
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (stype == BGP_CLEAR_SOFT_NONE) {
- peer_clear(peer, NULL);
- continue;
- }
-
if (!peer->afc[afi][safi])
continue;
- ret = peer_clear_soft(peer, afi, safi, stype);
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, NULL);
+ else
+ ret = peer_clear_soft(peer, afi, safi, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
}
+
+ if (!found)
+ vty_out(vty,
+ "%%BGP: No %s peer belonging to peer-group %s is configured\n",
+ afi_safi_print(afi, safi), arg);
+
return CMD_SUCCESS;
}
+ /* Clear all external (eBGP) neighbors. */
if (sort == clear_external) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->sort == BGP_PEER_IBGP)
continue;
+ if (!peer->afc[afi][safi])
+ continue;
+
if (stype == BGP_CLEAR_SOFT_NONE)
ret = peer_clear(peer, &nnode);
else
@@ -660,33 +679,44 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
}
+
+ if (!found)
+ vty_out(vty,
+ "%%BGP: No external %s peer is configured\n",
+ afi_safi_print(afi, safi));
+
return CMD_SUCCESS;
}
+ /* Clear all neighbors belonging to a specific AS. */
if (sort == clear_as) {
- as_t as;
- int find = 0;
-
- as = strtoul(arg, NULL, 10);
+ as_t as = strtoul(arg, NULL, 10);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->as != as)
continue;
- find = 1;
- if (stype == BGP_CLEAR_SOFT_NONE)
+ if (!peer->afc[afi][safi])
+ ret = BGP_ERR_AF_UNCONFIGURED;
+ else if (stype == BGP_CLEAR_SOFT_NONE)
ret = peer_clear(peer, &nnode);
else
ret = peer_clear_soft(peer, afi, safi, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
+ else
+ found = true;
}
- if (!find)
+
+ if (!found)
vty_out(vty,
- "%%BGP: No peer is configured with AS %s\n",
- arg);
+ "%%BGP: No %s peer is configured with AS %s\n",
+ afi_safi_print(afi, safi), arg);
+
return CMD_SUCCESS;
}
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 19561c031d..a0ff314786 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -140,7 +140,7 @@ EXTRA_DIST = frr-sphinx.mk \
manpages/index.rst \
manpages/isisd.rst \
manpages/ldpd.rst \
- manpages/Makefile \
+ manpages/Makefile.am \
manpages/mtracebis.rst \
manpages/nhrpd.rst \
manpages/ospf6d.rst \
@@ -182,7 +182,7 @@ EXTRA_DIST = frr-sphinx.mk \
developer/index.rst \
developer/ldpd-basic-test-setup.md \
developer/library.rst \
- developer/Makefile \
+ developer/Makefile.in \
developer/memtypes.rst \
developer/modules.rst \
developer/next-hop-tracking.rst \
@@ -195,6 +195,7 @@ EXTRA_DIST = frr-sphinx.mk \
user/babeld.rst \
user/basic.rst \
user/bgp.rst \
+ user/bugs.rst \
user/conf.py \
user/eigrpd.rst \
user/filter.rst \
@@ -205,7 +206,7 @@ EXTRA_DIST = frr-sphinx.mk \
user/ipv6.rst \
user/isisd.rst \
user/kernel.rst \
- user/Makefile \
+ user/Makefile.am \
user/nhrpd.rst \
user/ospf6d.rst \
user/ospfd.rst \
diff --git a/doc/developer/.gitignore b/doc/developer/.gitignore
index 2e7d8573f1..81c60dc0a3 100644
--- a/doc/developer/.gitignore
+++ b/doc/developer/.gitignore
@@ -1,3 +1,2 @@
/_templates
/_build
-!/Makefile.in
diff --git a/doc/developer/Makefile.in b/doc/developer/Makefile.am
index 76758f9242..76758f9242 100644
--- a/doc/developer/Makefile.in
+++ b/doc/developer/Makefile.am
diff --git a/doc/manpages/.gitignore b/doc/manpages/.gitignore
index 2e7d8573f1..81c60dc0a3 100644
--- a/doc/manpages/.gitignore
+++ b/doc/manpages/.gitignore
@@ -1,3 +1,2 @@
/_templates
/_build
-!/Makefile.in
diff --git a/doc/manpages/Makefile.in b/doc/manpages/Makefile.am
index f28746cee6..009c723823 100644
--- a/doc/manpages/Makefile.in
+++ b/doc/manpages/Makefile.am
@@ -34,11 +34,6 @@ include @srcdir@/../frr-sphinx.mk
# tags
# ctags
-# ignore these targets
-EMPTY_AUTOMAKE_TARGETS = dvi pdf ps tags ctags distdir installdirs check installcheck install-dvi install-ps install-html install-pdf install-info install-exec
-.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
-$(EMPTY_AUTOMAKE_TARGETS):
-
# These targets are automatically generated by Sphinx but conflict with
# implicitly defined Automake rules, so we manually override them to nothing.
# The other option is deleting the Sphinx-generated rules, which suppresses the
@@ -51,5 +46,3 @@ all: man
install-data: man
install: install-data
-
-mostlyclean distclean maintainer-clean: clean
diff --git a/doc/user/.gitignore b/doc/user/.gitignore
index 2e7d8573f1..81c60dc0a3 100644
--- a/doc/user/.gitignore
+++ b/doc/user/.gitignore
@@ -1,3 +1,2 @@
/_templates
/_build
-!/Makefile.in
diff --git a/doc/user/Makefile.in b/doc/user/Makefile.am
index 77c6abf917..64af2ff145 100644
--- a/doc/user/Makefile.in
+++ b/doc/user/Makefile.am
@@ -34,11 +34,6 @@ include @srcdir@/../frr-sphinx.mk
# tags
# ctags
-# ignore these targets
-EMPTY_AUTOMAKE_TARGETS = dvi ps tags ctags distdir install-exec install-dvi install-ps installdirs check installcheck install-html install-pdf install-data install
-.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
-$(EMPTY_AUTOMAKE_TARGETS):
-
# When building 'all', the logic is that we want to make docs that are easily
# readable by the person that just built them. Technically the reST source is
# readable in its own right, but we'll also build info and html because those
@@ -58,5 +53,3 @@ install-info: info
install-data: install-info
install: install-data
-
-mostlyclean distclean maintainer-clean: clean
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index bddf2ba26d..8080e001f1 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -180,6 +180,18 @@ Route Map Match Command
interface name specified if the neighbor was specified
in this manner.
+.. index:: match source-protocol PROTOCOL_NAME
+.. clicmd:: match source-protocol PROTOCOL_NAME
+
+ This is a ZEBRA specific match command. Matches the
+ originating protocol specified.
+
+.. index:: match source-instance NUMBER
+.. clicmd:: match source-instance NUMBER
+
+ This is a ZEBRA specific match command. The number is a range from (0-255).
+ Matches the originating protocols instance specified.
+
.. _route-map-set-command:
Route Map Set Command
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 0fe0cada39..8bd0683f14 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -260,12 +260,12 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
listnode_delete(old_route->nh_list,
rnh);
ospf6_nexthop_delete(rnh);
- route_updated = true;
}
}
listnode_delete(old_route->paths, o_path);
ospf6_path_free(o_path);
+ route_updated = true;
/* Current route's path (adv_router info) is similar
* to route being added.
@@ -273,6 +273,19 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
* Update FIB with effective NHs.
*/
if (listcount(old_route->paths)) {
+ for (ALL_LIST_ELEMENTS(old_route->paths,
+ anode, anext, o_path)) {
+ ospf6_merge_nexthops(
+ old_route->nh_list,
+ o_path->nh_list);
+ }
+ /* Update RIB/FIB with effective
+ * nh_list
+ */
+ if (ospf6->route_table->hook_add)
+ (*ospf6->route_table->hook_add)
+ (old_route);
+
if (old_route->path.origin.id
== route->path.origin.id
&& old_route->path.origin.adv_router
@@ -290,23 +303,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
old_route->path.origin.adv_router =
h_path->origin.adv_router;
}
-
- if (route_updated) {
- for (ALL_LIST_ELEMENTS(old_route->paths,
- anode, anext,
- o_path)) {
- ospf6_merge_nexthops(
- old_route->nh_list,
- o_path->nh_list);
- }
- /* Update RIB/FIB with effective
- * nh_list
- */
- if (ospf6->route_table->hook_add)
- (*ospf6->route_table->hook_add)(
- old_route);
- break;
- }
+ break;
} else {
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&old_route->prefix, buf,
@@ -374,13 +371,6 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
/* Add a nh_list to new ecmp path */
ospf6_copy_nexthops(ecmp_path->nh_list,
route->nh_list);
- /* Merge nexthop to existing route's nh_list */
- ospf6_route_merge_nexthops(old_route, route);
-
- /* Update RIB/FIB */
- if (ospf6->route_table->hook_add)
- (*ospf6->route_table->hook_add)(
- old_route);
/* Add the new path to route's path list */
listnode_add_sort(old_route->paths, ecmp_path);
@@ -400,46 +390,52 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
listcount(old_route->nh_list));
}
} else {
- for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
- nnode, nh)) {
- for (ALL_LIST_ELEMENTS(
- old_route->nh_list, rnode,
- rnext, rnh)) {
- if (!ospf6_nexthop_is_same(rnh,
- nh))
- continue;
-
- listnode_delete(
- old_route->nh_list,
- rnh);
- ospf6_nexthop_delete(rnh);
- }
- }
list_delete_all_node(o_path->nh_list);
ospf6_copy_nexthops(o_path->nh_list,
route->nh_list);
+ }
- /* Merge nexthop to existing route's nh_list */
- ospf6_route_merge_nexthops(old_route, route);
+ /* Reset nexthop lists, rebuild from brouter table
+ * for each adv. router.
+ */
+ list_delete_all_node(old_route->nh_list);
- if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
- prefix2str(&route->prefix, buf,
- sizeof(buf));
- zlog_debug(
- "%s: existing route %s with effective nh count %u",
- __PRETTY_FUNCTION__, buf,
- old_route->nh_list
- ? listcount(
- old_route
- ->nh_list)
- : 0);
+ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
+ o_path)) {
+ struct ospf6_route *asbr_entry;
+
+ asbr_entry = ospf6_route_lookup(
+ &o_path->ls_prefix,
+ ospf6->brouter_table);
+ if (asbr_entry == NULL) {
+ if (IS_OSPF6_DEBUG_EXAMIN(
+ AS_EXTERNAL)) {
+ prefix2str(&old_route->prefix,
+ buf, sizeof(buf));
+ zlog_debug("%s: ls_prfix %s asbr_entry not found.",
+ __PRETTY_FUNCTION__,
+ buf);
+ }
+ continue;
}
+ ospf6_route_merge_nexthops(old_route,
+ asbr_entry);
+ }
- /* Update RIB/FIB */
- if (ospf6->route_table->hook_add)
- (*ospf6->route_table->hook_add)(
- old_route);
+ if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
+ prefix2str(&route->prefix, buf, sizeof(buf));
+ zlog_debug("%s: route %s with effective paths %u nh %u",
+ __PRETTY_FUNCTION__, buf,
+ old_route->paths ?
+ listcount(old_route->paths) : 0,
+ old_route->nh_list ?
+ listcount(old_route->nh_list) : 0);
}
+
+ /* Update RIB/FIB */
+ if (ospf6->route_table->hook_add)
+ (*ospf6->route_table->hook_add)(old_route);
+
/* Delete the new route its info added to existing
* route.
*/
@@ -509,8 +505,9 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
route->path.origin.type = lsa->header->type;
route->path.origin.id = lsa->header->id;
route->path.origin.adv_router = lsa->header->adv_router;
-
route->path.prefix_options = external->prefix.prefix_options;
+ memcpy(&route->path.ls_prefix, &asbr_id, sizeof(struct prefix));
+
if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) {
route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
route->path.metric_type = 2;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 26e6deadae..d99541ebad 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -2037,6 +2037,8 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
options, capa, brouter->path.metric_type, brouter->path.cost,
brouter->path.u.cost_e2);
+ zlog_info(" paths %u nh %u", listcount(brouter->paths),
+ listcount(brouter->nh_list));
}
void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
index 1c80cf055a..a478b416bf 100644
--- a/sharpd/sharp_main.c
+++ b/sharpd/sharp_main.c
@@ -149,6 +149,8 @@ int main(int argc, char **argv, char **envp)
vrf_init(NULL, NULL, NULL, NULL);
+ route_map_init();
+
sharp_zebra_init();
/* Get configuration file. */
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 4d19484a64..956da9d4ed 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -81,14 +81,16 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
+ "sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes [instance (0-255)$instance]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
"Address to start /32 generation at\n"
"Nexthop to use\n"
"Nexthop address\n"
- "How many to create\n")
+ "How many to create\n"
+ "Instance to use\n"
+ "Instance\n")
{
int i;
struct prefix p;
@@ -112,7 +114,7 @@ DEFPY (install_routes,
temp = ntohl(p.u.prefix4.s_addr);
for (i = 0; i < routes; i++) {
- route_add(&p, &nhop);
+ route_add(&p, (uint8_t)instance, &nhop);
p.u.prefix4.s_addr = htonl(++temp);
}
@@ -151,17 +153,18 @@ DEFPY(vrf_label, vrf_label_cmd,
DEFPY (remove_routes,
remove_routes_cmd,
- "sharp remove routes A.B.C.D$start (1-1000000)$routes",
+ "sharp remove routes A.B.C.D$start (1-1000000)$routes [instance (0-255)$instance]",
"Sharp Routing Protocol\n"
"Remove some routes\n"
"Routes to remove\n"
"Starting spot\n"
- "Routes to uniinstall\n")
+ "Routes to uniinstall\n"
+ "instance to use\n"
+ "Value of instance\n")
{
int i;
struct prefix p;
uint32_t temp;
-
total_routes = routes;
removed_routes = 0;
@@ -175,7 +178,7 @@ DEFPY (remove_routes,
temp = ntohl(p.u.prefix4.s_addr);
for (i = 0; i < routes; i++) {
- route_delete(&p);
+ route_delete(&p, (uint8_t)instance);
p.u.prefix4.s_addr = htonl(++temp);
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 999255e925..fcb555170b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -176,7 +176,7 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
}
-void route_add(struct prefix *p, struct nexthop *nh)
+void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
@@ -184,6 +184,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
+ api.instance = instance;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@@ -200,7 +201,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
-void route_delete(struct prefix *p)
+void route_delete(struct prefix *p, uint8_t instance)
{
struct zapi_route api;
@@ -208,6 +209,7 @@ void route_delete(struct prefix *p)
api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
+ api.instance = instance;
memcpy(&api.prefix, p, sizeof(*p));
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index 0c906fc4ff..58438ed01d 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -25,7 +25,7 @@
extern void sharp_zebra_init(void);
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
-extern void route_add(struct prefix *p, struct nexthop *nh);
-extern void route_delete(struct prefix *p);
+extern void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh);
+extern void route_delete(struct prefix *p, uint8_t instance);
extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch);
#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 703c1d05fc..6a19325927 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -215,6 +215,7 @@ EXTRA_DIST = \
lib/test_ttable.refout \
lib/test_zlog.py \
lib/test_graph.py \
+ lib/test_graph.refout \
ospf6d/test_lsdb.py \
ospf6d/test_lsdb.in \
ospf6d/test_lsdb.refout \
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 4974e538ea..30de9d7711 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -846,27 +846,29 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
return (retcode);
}
-/* We don't care about the point of the cursor when '?' is typed. */
-static int vtysh_rl_describe(void)
+/*
+ * Function processes cli commands terminated with '?' character when entered
+ * through either 'vtysh' or 'vtysh -c' interfaces.
+ */
+static int vtysh_process_questionmark(const char *input, int input_len)
{
- int ret;
+ int ret, width = 0;
unsigned int i;
- vector vline;
- vector describe;
- int width;
+ vector vline, describe;
struct cmd_token *token;
- vline = cmd_make_strvec(rl_line_buffer);
+ if (!input)
+ return 1;
+
+ vline = cmd_make_strvec(input);
/* In case of '> ?'. */
if (vline == NULL) {
vline = vector_init(1);
vector_set(vline, NULL);
- } else if (rl_end && isspace((int)rl_line_buffer[rl_end - 1]))
+ } else if (input_len && isspace((int)input[input_len - 1]))
vector_set(vline, NULL);
- fprintf(stdout, "\n");
-
describe = cmd_describe_command(vline, vty, &ret);
/* Ambiguous and no match error. */
@@ -875,7 +877,6 @@ static int vtysh_rl_describe(void)
cmd_free_strvec(vline);
vector_free(describe);
fprintf(stdout, "%% Ambiguous command.\n");
- rl_on_new_line();
return 0;
break;
case CMD_ERR_NO_MATCH:
@@ -883,7 +884,6 @@ static int vtysh_rl_describe(void)
if (describe)
vector_free(describe);
fprintf(stdout, "%% There is no matched command.\n");
- rl_on_new_line();
return 0;
break;
}
@@ -933,9 +933,61 @@ static int vtysh_rl_describe(void)
cmd_free_strvec(vline);
vector_free(describe);
+ return 0;
+}
+
+/*
+ * Entry point for user commands terminated with '?' character and typed through
+ * the usual vtysh's stdin interface. This is the function being registered with
+ * readline() api's.
+ */
+static int vtysh_rl_describe(void)
+{
+ int ret;
+
+ fprintf(stdout, "\n");
+
+ ret = vtysh_process_questionmark(rl_line_buffer, rl_end);
rl_on_new_line();
- return 0;
+ return ret;
+}
+
+/*
+ * Function in charged of processing vtysh instructions terminating with '?'
+ * character and received through the 'vtysh -c' interface. If user's
+ * instruction is well-formatted, we will call the same processing routine
+ * utilized by the traditional vtysh's stdin interface.
+ */
+int vtysh_execute_command_questionmark(char *input)
+{
+ int input_len, qmark_count = 0;
+ const char *str;
+
+ if (!(input && *input))
+ return 1;
+
+ /* Finding out question_mark count and strlen */
+ for (str = input; *str; ++str) {
+ if (*str == '?')
+ qmark_count++;
+ }
+ input_len = str - input;
+
+ /*
+ * Verify that user's input terminates in '?' and that patterns such as
+ * 'cmd ? subcmd ?' are prevented.
+ */
+ if (qmark_count != 1 || input[input_len - 1] != '?')
+ return 1;
+
+ /*
+ * Questionmark-processing function is not expecting to receive '?'
+ * character in input string.
+ */
+ input[input_len - 1] = '\0';
+
+ return vtysh_process_questionmark(input, input_len - 1);
}
/* Result of cmd_complete_command() call will be stored here
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index f3e58f309e..ccfdd6557b 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -71,6 +71,7 @@ void vtysh_user_init(void);
int vtysh_execute(const char *);
int vtysh_execute_no_pager(const char *);
+int vtysh_execute_command_questionmark(char *input);
char *vtysh_prompt(void);
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index cd59d8094b..3dd70983bc 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -611,7 +611,16 @@ int main(int argc, char **argv, char **env)
if (logfile)
log_it(cmd->line);
- ret = vtysh_execute_no_pager(cmd->line);
+ /*
+ * Parsing logic for regular commands will be different than
+ * for those commands requiring further processing, such as
+ * cli instructions terminating with question-mark character.
+ */
+ if (!vtysh_execute_command_questionmark(cmd->line))
+ ret = CMD_SUCCESS;
+ else
+ ret = vtysh_execute_no_pager(cmd->line);
+
if (!no_error
&& !(ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON
|| ret == CMD_WARNING))
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 5a6565aec9..b1387815ba 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -539,8 +539,8 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
afi = family2afi(rn->p.family);
if (rmap_name)
ret = zebra_import_table_route_map_check(
- afi, re->type, &rn->p, re->ng.nexthop, re->vrf_id,
- re->tag, rmap_name);
+ afi, re->type, re->instance, &rn->p, re->ng.nexthop,
+ re->vrf_id, re->tag, rmap_name);
if (ret != RMAP_MATCH) {
UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 9510a0e12c..2fd7bee056 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1308,8 +1308,7 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
struct zebra_ns *zns = zebra_ns_lookup(ns_id);
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
@@ -1666,8 +1665,7 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
struct zebra_ns *zns;
zns = zvrf->zns;
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
@@ -1759,8 +1757,7 @@ static int netlink_vxlan_flood_list_update(struct interface *ifp,
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
zns = zvrf->zns;
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
@@ -2075,8 +2072,7 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
return -1;
}
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
@@ -2392,8 +2388,7 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
zns = zvrf->zns;
- memset(&req.n, 0, sizeof(req.n));
- memset(&req.ndm, 0, sizeof(req.ndm));
+ memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 7ec640164a..dec4ed06a9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -924,7 +924,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
/* It'll get set if required inside */
- ret = zebra_route_map_check(family, re->type, p, nexthop,
+ ret = zebra_route_map_check(family, re->type, re->instance, p, nexthop,
nexthop->vrf_id, re->tag);
if (ret == RMAP_DENYMATCH) {
if (IS_ZEBRA_DEBUG_RIB) {
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 013e841a5c..10ba88880a 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -49,6 +49,7 @@ struct nh_rmap_obj {
struct nexthop *nexthop;
vrf_id_t vrf_id;
uint32_t source_protocol;
+ uint8_t instance;
int metric;
route_tag_t tag;
};
@@ -287,7 +288,7 @@ DEFUN (no_match_ip_nexthop_prefix_len,
DEFUN (match_source_protocol,
match_source_protocol_cmd,
- "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>",
+ "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
MATCH_STR
"Match protocol via which the route was learnt\n"
"BGP protocol\n"
@@ -303,7 +304,8 @@ DEFUN (match_source_protocol,
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
- "Statically configured routes\n")
+ "Statically configured routes\n"
+ "SHARP process\n")
{
char *proto = argv[2]->text;
int i;
@@ -319,7 +321,7 @@ DEFUN (match_source_protocol,
DEFUN (no_match_source_protocol,
no_match_source_protocol_cmd,
- "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]",
+ "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
NO_STR
MATCH_STR
"No match protocol via which the route was learnt\n"
@@ -336,13 +338,40 @@ DEFUN (no_match_source_protocol,
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
- "Statically configured routes\n")
+ "Statically configured routes\n"
+ "SHARP process\n")
{
char *proto = (argc == 4) ? argv[3]->text : NULL;
return zebra_route_match_delete(vty, "source-protocol", proto,
RMAP_EVENT_MATCH_DELETED);
}
+DEFUN (match_source_instance,
+ match_source_instance_cmd,
+ "match source-instance (0-255)",
+ MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ char *instance = argv[2]->arg;
+
+ return zebra_route_match_add(vty, "source-instance", instance,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
+DEFUN (no_match_source_instance,
+ no_match_source_instance_cmd,
+ "no match source-instance [(0-255)]",
+ NO_STR MATCH_STR
+ "Match the protocol's instance number\n"
+ "The instance number\n")
+{
+ char *instance = (argc == 4) ? argv[3]->arg : NULL;
+
+ return zebra_route_match_delete(vty, "source-instance", instance,
+ RMAP_EVENT_MATCH_ADDED);
+}
+
/* set functions */
DEFUN (set_src,
@@ -1172,6 +1201,47 @@ static struct route_map_rule_cmd route_match_source_protocol_cmd = {
"source-protocol", route_match_source_protocol,
route_match_source_protocol_compile, route_match_source_protocol_free};
+/* `source-instance` */
+static route_map_result_t route_match_source_instance(void *rule,
+ struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+{
+ uint8_t *instance = (uint8_t *)rule;
+ struct nh_rmap_obj *nh_data;
+
+ if (type != RMAP_ZEBRA)
+ return RMAP_NOMATCH;
+
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_DENYMATCH;
+
+ return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
+}
+
+static void *route_match_source_instance_compile(const char *arg)
+{
+ uint8_t *instance;
+ int i;
+
+ i = atoi(arg);
+ instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
+
+ *instance = i;
+
+ return instance;
+}
+
+static void route_match_source_instance_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_source_instance_cmd = {
+ "source-instance", route_match_source_instance,
+ route_match_source_instance_compile, route_match_source_instance_free};
+
/* `set src A.B.C.D' */
/* Set src. */
@@ -1252,7 +1322,7 @@ void zebra_route_map_write_delay_timer(struct vty *vty)
}
route_map_result_t zebra_route_map_check(int family, int rib_type,
- struct prefix *p,
+ uint8_t instance, struct prefix *p,
struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag)
{
@@ -1263,6 +1333,7 @@ route_map_result_t zebra_route_map_check(int family, int rib_type,
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = vrf_id;
nh_obj.source_protocol = rib_type;
+ nh_obj.instance = instance;
nh_obj.metric = 0;
nh_obj.tag = tag;
@@ -1296,9 +1367,10 @@ void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
}
route_map_result_t
-zebra_import_table_route_map_check(int family, int re_type, struct prefix *p,
- struct nexthop *nexthop, vrf_id_t vrf_id,
- route_tag_t tag, const char *rmap_name)
+zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
+ struct prefix *p, struct nexthop *nexthop,
+ vrf_id_t vrf_id, route_tag_t tag,
+ const char *rmap_name)
{
struct route_map *rmap = NULL;
route_map_result_t ret = RMAP_DENYMATCH;
@@ -1307,6 +1379,7 @@ zebra_import_table_route_map_check(int family, int re_type, struct prefix *p,
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = vrf_id;
nh_obj.source_protocol = re_type;
+ nh_obj.instance = instance;
nh_obj.metric = 0;
nh_obj.tag = tag;
@@ -1331,6 +1404,7 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = nexthop->vrf_id;
nh_obj.source_protocol = re->type;
+ nh_obj.instance = re->instance;
nh_obj.metric = re->metric;
nh_obj.tag = re->tag;
@@ -1471,6 +1545,8 @@ void zebra_route_map_init()
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
route_map_install_match(&route_match_source_protocol_cmd);
+ route_map_install_match(&route_match_source_instance_cmd);
+
/* */
route_map_install_set(&route_set_src_cmd);
/* */
@@ -1482,6 +1558,9 @@ void zebra_route_map_init()
install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
install_element(RMAP_NODE, &match_source_protocol_cmd);
install_element(RMAP_NODE, &no_match_source_protocol_cmd);
+ install_element(RMAP_NODE, &match_source_instance_cmd);
+ install_element(RMAP_NODE, &no_match_source_instance_cmd);
+
/* */
install_element(RMAP_NODE, &set_src_cmd);
install_element(RMAP_NODE, &no_set_src_cmd);
diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h
index 14c7c58848..20d425a2bc 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -34,14 +34,14 @@ extern void zebra_del_import_table_route_map(afi_t afi, uint32_t table);
extern void zebra_route_map_write_delay_timer(struct vty *);
extern route_map_result_t
-zebra_import_table_route_map_check(int family, int rib_type, struct prefix *p,
- struct nexthop *nexthop, vrf_id_t vrf_id,
- route_tag_t tag, const char *rmap_name);
-extern route_map_result_t zebra_route_map_check(int family, int rib_type,
- struct prefix *p,
- struct nexthop *nexthop,
- vrf_id_t vrf_id,
- route_tag_t tag);
+zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance,
+ struct prefix *p, struct nexthop *nexthop,
+ vrf_id_t vrf_id, route_tag_t tag,
+ const char *rmap_name);
+extern route_map_result_t
+zebra_route_map_check(int family, int rib_type, uint8_t instance,
+ struct prefix *p, struct nexthop *nexthop,
+ vrf_id_t vrf_id, route_tag_t tag);
extern route_map_result_t
zebra_nht_route_map_check(int family, int client_proto, struct prefix *p,
struct route_entry *, struct nexthop *nexthop);