summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--babeld/babel_zebra.c2
-rw-r--r--bgpd/Makefile.am8
-rw-r--r--bgpd/bgp_attr.c26
-rw-r--r--bgpd/bgp_attr.h1
-rw-r--r--bgpd/bgp_route.c180
-rw-r--r--bgpd/bgp_vty.c63
-rw-r--r--bgpd/bgp_zebra.c2
-rw-r--r--bgpd/rfapi/vnc_zebra.c2
-rwxr-xr-xconfigure.ac1
-rw-r--r--eigrpd/eigrp_zebra.c17
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--ldpd/lde.c2
-rw-r--r--ldpd/ldp_zebra.c2
-rw-r--r--lib/json.h15
-rw-r--r--lib/log.c5
-rw-r--r--lib/route_types.txt2
-rw-r--r--lib/zclient.c35
-rw-r--r--lib/zclient.h31
-rw-r--r--nhrpd/nhrp_route.c2
-rw-r--r--ospf6d/ospf6_area.c4
-rw-r--r--ospf6d/ospf6_intra.c6
-rw-r--r--ospf6d/ospf6_spf.c244
-rw-r--r--ospf6d/ospf6_spf.h1
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_vty.c608
-rw-r--r--ospfd/ospf_zebra.c2
-rw-r--r--ospfd/ospfd.h4
-rw-r--r--pimd/pim_zebra.c2
-rw-r--r--pimd/pim_zlookup.c2
-rw-r--r--redhat/daemons2
-rw-r--r--ripd/rip_zebra.c2
-rw-r--r--ripngd/ripng_zebra.c2
-rw-r--r--sharpd/sharp_main.c162
-rw-r--r--sharpd/sharp_vty.c114
-rw-r--r--sharpd/sharp_vty.h26
-rw-r--r--sharpd/sharp_zebra.c208
-rw-r--r--sharpd/sharp_zebra.h29
-rw-r--r--sharpd/sharpd.conf.sample3
-rw-r--r--sharpd/subdir.am21
-rw-r--r--tests/bgpd/test_mpath.c2
-rw-r--r--tests/test_lblmgr.c2
-rw-r--r--tools/etc/frr/daemons1
-rw-r--r--tools/etc/frr/daemons.conf1
-rw-r--r--tools/etc/iproute2/rt_protos.d/frr.conf1
-rwxr-xr-xtools/frr2
-rw-r--r--vtysh/Makefile.am4
-rwxr-xr-xvtysh/extract.pl.in2
-rw-r--r--vtysh/vtysh.c9
-rw-r--r--vtysh/vtysh.h4
-rw-r--r--zebra/client_main.c2
-rw-r--r--zebra/label_manager.c2
-rw-r--r--zebra/rt_netlink.c5
-rw-r--r--zebra/rt_netlink.h1
-rw-r--r--zebra/zebra_rib.c14
-rw-r--r--zebra/zebra_vxlan.c6
-rw-r--r--zebra/zserv.c46
-rw-r--r--zebra/zserv.h8
58 files changed, 1586 insertions, 369 deletions
diff --git a/Makefile.am b/Makefile.am
index dfa9d7a175..2468dc733d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ include nhrpd/subdir.am
include ldpd/subdir.am
include babeld/subdir.am
include eigrpd/subdir.am
+include sharpd/subdir.am
include pimd/subdir.am
SUBDIRS = . @LIBRFP@ @RFPTEST@ \
diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c
index e7c27e8e21..8dea1431e2 100644
--- a/babeld/babel_zebra.c
+++ b/babeld/babel_zebra.c
@@ -237,7 +237,7 @@ babel_zebra_connected (struct zclient *zclient)
void babelz_zebra_init(void)
{
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);
zclient->zebra_connected = babel_zebra_connected;
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index 19cb1cf03a..fa1dcbb762 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -73,6 +73,8 @@ module_LTLIBRARIES =
sbin_PROGRAMS = bgpd
bin_PROGRAMS = bgp_btoa
+BUILT_SOURCES =
+
libbgp_a_SOURCES = \
bgp_memory.c \
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
@@ -116,13 +118,9 @@ bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
if RPKI
module_LTLIBRARIES += bgpd_rpki.la
+BUILT_SOURCES += bgp_rpki_clippy.c
endif
-bgpd_rpki_la-bgp_rpki.o: bgp_rpki_clippy.c
-bgp_rpki.la: bgp_rpki_clippy.c
-bgp_rpki.lo: bgp_rpki_clippy.c
-bgp_rpki.o: bgp_rpki_clippy.c
-
bgpd_rpki_la_SOURCES = bgp_rpki.c
bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 76fc8f968e..6ddb2ec8a7 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -822,6 +822,32 @@ void bgp_attr_unintern_sub(struct attr *attr)
#endif
}
+/*
+ * We have some show commands that let you experimentally
+ * apply a route-map. When we apply the route-map
+ * we are reseting values but not saving them for
+ * posterity via intern'ing( because route-maps don't
+ * do that) but at this point in time we need
+ * to compare the new attr to the old and if the
+ * routemap has changed it we need to, as Snoop Dog says,
+ * Drop it like it's hot
+ */
+void bgp_attr_undup(struct attr *new, struct attr *old)
+{
+ if (new->aspath != old->aspath)
+ aspath_free(new->aspath);
+
+ if (new->community != old->community)
+ community_free(new->community);
+
+ if (new->ecommunity != old->ecommunity)
+ ecommunity_free(&new->ecommunity);
+
+ if (new->lcommunity != old->lcommunity)
+ lcommunity_free(&new->lcommunity);
+
+}
+
/* Free bgp attribute and aspath. */
void bgp_attr_unintern(struct attr **pattr)
{
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 80ff36b59f..f694f01adb 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -239,6 +239,7 @@ extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *,
bgp_size_t, struct bgp_nlri *,
struct bgp_nlri *);
extern void bgp_attr_dup(struct attr *, struct attr *);
+extern void bgp_attr_undup(struct attr *new, struct attr *old);
extern struct attr *bgp_attr_intern(struct attr *attr);
extern void bgp_attr_unintern_sub(struct attr *);
extern void bgp_attr_unintern(struct attr **);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index a5f9c5f2ab..a655bd0b6f 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1157,49 +1157,52 @@ static int bgp_output_modifier(struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
const char *rmap_name)
{
- struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
struct route_map *rmap = NULL;
+ u_char rmap_type;
- filter = &peer->filter[afi][safi];
+ /*
+ * So if we get to this point and have no rmap_name
+ * we want to just show the output as it currently
+ * exists.
+ */
+ if (!rmap_name)
+ return RMAP_PERMIT;
/* Apply default weight value. */
if (peer->weight[afi][safi])
attr->weight = peer->weight[afi][safi];
- if (rmap_name) {
- rmap = route_map_lookup_by_name(rmap_name);
-
- if (rmap == NULL)
- return RMAP_DENY;
- } else {
- if (ROUTE_MAP_OUT_NAME(filter)) {
- rmap = ROUTE_MAP_OUT(filter);
+ rmap = route_map_lookup_by_name(rmap_name);
- if (rmap == NULL)
- return RMAP_DENY;
- }
- }
+ /*
+ * If we have a route map name and we do not find
+ * the routemap that means we have an implicit
+ * deny.
+ */
+ if (rmap == NULL)
+ return RMAP_DENY;
/* Route map apply. */
- if (rmap) {
- /* Duplicate current value to new strucutre for modification. */
- info.peer = peer;
- info.attr = attr;
+ /* Duplicate current value to new strucutre for modification. */
+ info.peer = peer;
+ info.attr = attr;
- SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
+ rmap_type = peer->rmap_type;
+ SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
- /* Apply BGP route map to the attribute. */
- ret = route_map_apply(rmap, p, RMAP_BGP, &info);
+ /* Apply BGP route map to the attribute. */
+ ret = route_map_apply(rmap, p, RMAP_BGP, &info);
- peer->rmap_type = 0;
+ peer->rmap_type = rmap_type;
+
+ if (ret == RMAP_DENYMATCH)
+ /*
+ * caller has multiple error paths with bgp_attr_flush()
+ */
+ return RMAP_DENY;
- if (ret == RMAP_DENYMATCH)
- /* caller has multiple error paths with bgp_attr_flush()
- */
- return RMAP_DENY;
- }
return RMAP_PERMIT;
}
@@ -10180,70 +10183,75 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
}
} else {
for (adj = rn->adj_out; adj; adj = adj->next)
- SUBGRP_FOREACH_PEER (adj->subgroup, paf)
- if (paf->peer == peer) {
- if (header1) {
- if (use_json) {
- json_object_int_add(
- json,
- "bgpTableVersion",
- table->version);
- json_object_string_add(
- json,
- "bgpLocalRouterId",
- inet_ntoa(
- bgp->router_id));
- json_object_object_add(
- json,
- "bgpStatusCodes",
- json_scode);
- json_object_object_add(
- json,
- "bgpOriginCodes",
- json_ocode);
- } else {
- vty_out(vty,
- "BGP table version is %" PRIu64
- ", local router ID is %s\n",
- table->version,
- inet_ntoa(
- bgp->router_id));
- vty_out(vty,
- BGP_SHOW_SCODE_HEADER);
- vty_out(vty,
- BGP_SHOW_OCODE_HEADER);
- }
- header1 = 0;
- }
+ SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
+ if (paf->peer != peer)
+ continue;
- if (header2) {
- if (!use_json)
- vty_out(vty,
- BGP_SHOW_HEADER);
- header2 = 0;
+ if (header1) {
+ if (use_json) {
+ json_object_int_add(
+ json,
+ "bgpTableVersion",
+ table->version);
+ json_object_string_add(
+ json,
+ "bgpLocalRouterId",
+ inet_ntoa(
+ bgp->router_id));
+ json_object_object_add(
+ json,
+ "bgpStatusCodes",
+ json_scode);
+ json_object_object_add(
+ json,
+ "bgpOriginCodes",
+ json_ocode);
+ } else {
+ vty_out(vty,
+ "BGP table version is %" PRIu64
+ ", local router ID is %s\n",
+ table->version,
+ inet_ntoa(
+ bgp->router_id));
+ vty_out(vty,
+ BGP_SHOW_SCODE_HEADER);
+ vty_out(vty,
+ BGP_SHOW_OCODE_HEADER);
}
+ header1 = 0;
+ }
+
+ if (header2) {
+ if (!use_json)
+ vty_out(vty,
+ BGP_SHOW_HEADER);
+ header2 = 0;
+ }
- if (adj->attr) {
- bgp_attr_dup(&attr,
- adj->attr);
- ret = bgp_output_modifier(
- peer, &rn->p,
- &attr, afi,
+ if (adj->attr) {
+ bgp_attr_dup(&attr,
+ adj->attr);
+ ret = bgp_output_modifier(
+ peer, &rn->p,
+ &attr, afi,
+ safi,
+ rmap_name);
+ if (ret != RMAP_DENY) {
+ route_vty_out_tmp(
+ vty,
+ &rn->p,
+ &attr,
safi,
- rmap_name);
- if (ret != RMAP_DENY) {
- route_vty_out_tmp(
- vty,
- &rn->p,
- &attr,
- safi,
- use_json,
- json_ar);
- output_count++;
- } else
- filtered_count++;
- }
+ use_json,
+ json_ar);
+ output_count++;
+ } else
+ filtered_count++;
+
+ bgp_attr_undup(&attr,
+ adj->attr);
}
+ }
}
}
if (use_json)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index b0af5f2ced..9159bc683d 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -6313,7 +6313,7 @@ DEFUN (clear_ip_bgp_prefix,
int idx = 0;
/* [<view|vrf> VIEWVRFNAME] */
- if (argv_find(argv, argc, "WORD", &idx))
+ if (argv_find(argv, argc, "VIEWVRFNAME", &idx))
vrf = argv[idx]->arg;
prefix = argv[argc - 1]->arg;
@@ -10461,60 +10461,39 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
return CMD_SUCCESS;
}
-/* Show BGP peer group's information. */
-enum show_group_type { show_all_groups, show_peer_group };
-
-static int bgp_show_peer_group(struct vty *vty, struct bgp *bgp,
- enum show_group_type type,
- const char *group_name)
+static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
+ const char *group_name)
{
+ struct bgp *bgp;
struct listnode *node, *nnode;
struct peer_group *group;
- int find = 0;
+ bool found = false;
+
+ bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
+ if (!bgp) {
+ vty_out(vty, "%% No such BGP instance exists\n");
+ return CMD_WARNING;
+ }
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
- switch (type) {
- case show_all_groups:
- bgp_show_one_peer_group(vty, group);
- break;
- case show_peer_group:
- if (group_name
- && (strcmp(group->name, group_name) == 0)) {
- find = 1;
+ if (group_name) {
+ if (strmatch(group->name, group_name)) {
bgp_show_one_peer_group(vty, group);
+ found = true;
+ break;
}
- break;
+ } else {
+ bgp_show_one_peer_group(vty, group);
}
}
- if (type == show_peer_group && !find)
+ if (group_name && !found)
vty_out(vty, "%% No such peer-group\n");
return CMD_SUCCESS;
}
-static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
- enum show_group_type type,
- const char *group_name)
-{
- struct bgp *bgp;
- int ret = CMD_SUCCESS;
-
- if (name)
- bgp = bgp_lookup_by_name(name);
- else
- bgp = bgp_get_default();
-
- if (!bgp) {
- vty_out(vty, "%% No such BGP instance exist\n");
- return CMD_WARNING;
- }
-
- ret = bgp_show_peer_group(vty, bgp, type, group_name);
-
- return ret;
-}
-
DEFUN (show_ip_bgp_peer_groups,
show_ip_bgp_peer_groups_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME]",
@@ -10529,10 +10508,10 @@ DEFUN (show_ip_bgp_peer_groups,
vrf = pg = NULL;
int idx = 0;
- vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL;
+ vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg : NULL;
pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL;
- return bgp_show_peer_group_vty(vty, vrf, show_all_groups, pg);
+ return bgp_show_peer_group_vty(vty, vrf, pg);
}
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index b6bf008bae..1cf04abfce 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1759,7 +1759,7 @@ void bgp_zebra_init(struct thread_master *master)
zclient_num_connects = 0;
/* Set default values. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->router_id_update = bgp_router_id_update;
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index 478d3b5ac7..5c71df238f 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -892,7 +892,7 @@ extern struct zebra_privs_t bgpd_privs;
void vnc_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient_vnc = zclient_new(master);
+ zclient_vnc = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
diff --git a/configure.ac b/configure.ac
index cdbd48fe3c..16cc8901a3 100755
--- a/configure.ac
+++ b/configure.ac
@@ -201,6 +201,7 @@ else
fi
fi
AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"])
+AM_CONDITIONAL([SHARPD], [test "x$enable_dev_build" = "xyes"])
dnl always want these CFLAGS
AC_C_FLAG([-fno-omit-frame-pointer])
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 9076a50f57..00438f2f47 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -94,6 +94,18 @@ static int eigrp_router_id_update_zebra(int command, struct zclient *zclient,
return 0;
}
+static int eigrp_zebra_notify_owner(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct prefix p;
+ enum zapi_route_notify_owner note;
+
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &note))
+ return -1;
+
+ return 0;
+}
+
static void eigrp_zebra_connected(struct zclient *zclient)
{
zclient_send_reg_requests(zclient, VRF_DEFAULT);
@@ -101,7 +113,9 @@ static void eigrp_zebra_connected(struct zclient *zclient)
void eigrp_zebra_init(void)
{
- zclient = zclient_new(master);
+ struct zclient_options opt = { .receive_notify = false };
+
+ zclient = zclient_new_notify(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
zclient->zebra_connected = eigrp_zebra_connected;
@@ -114,6 +128,7 @@ void eigrp_zebra_init(void)
zclient->interface_address_delete = eigrp_interface_address_delete;
zclient->redistribute_route_add = eigrp_zebra_read_route;
zclient->redistribute_route_del = eigrp_zebra_read_route;
+ zclient->notify_owner = eigrp_zebra_notify_owner;
}
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index c186dd56ad..573b81591c 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -411,7 +411,7 @@ static void isis_zebra_connected(struct zclient *zclient)
void isis_zebra_init(struct thread_master *master)
{
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0, &isisd_privs);
zclient->zebra_connected = isis_zebra_connected;
zclient->router_id_update = isis_router_id_update_zebra;
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 8122b88cca..b597d967d7 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -1618,7 +1618,7 @@ static void
zclient_sync_init(u_short instance)
{
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new(master);
+ zclient_sync = zclient_new_notify(master, &zclient_options_default);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->instance = instance;
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 8fe51cb9d1..e703a9ff61 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -513,7 +513,7 @@ void
ldp_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs);
/* set callbacks */
diff --git a/lib/json.h b/lib/json.h
index e3e55ab962..675d852af7 100644
--- a/lib/json.h
+++ b/lib/json.h
@@ -52,4 +52,19 @@ extern void json_object_free(struct json_object *obj);
#define JSON_STR "JavaScript Object Notation\n"
+/* NOTE: json-c lib has following commit 316da85 which
+ * handles escape of forward slash.
+ * This allows prefix "20.0.14.0\/24":{
+ * to "20.0.14.0/24":{ some platforms do not have
+ * latest copy of json-c where defining below macro.
+ */
+
+#ifndef JSON_C_TO_STRING_NOSLASHESCAPE
+
+/**
+ * Don't escape forward slashes.
+ */
+#define JSON_C_TO_STRING_NOSLASHESCAPE (1<<4)
+#endif
+
#endif /* _QUAGGA_JSON_H */
diff --git a/lib/log.c b/lib/log.c
index 02af55d465..7589934b69 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -897,6 +897,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER),
DESC_ENTRY(ZEBRA_ROUTE_ADD),
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
+ DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
@@ -1044,6 +1045,8 @@ int proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_NHRP;
else if (strmatch(s, "babel"))
return ZEBRA_ROUTE_BABEL;
+ else if (strmatch(s, "sharp"))
+ return ZEBRA_ROUTE_SHARP;
}
if (afi == AFI_IP6) {
if (strmatch(s, "kernel"))
@@ -1070,6 +1073,8 @@ int proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_NHRP;
else if (strmatch(s, "babel"))
return ZEBRA_ROUTE_BABEL;
+ else if (strmatch(s, "sharp"))
+ return ZEBRA_ROUTE_SHARP;
}
return -1;
}
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 386d9992f7..4e764a14c1 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -77,6 +77,7 @@ ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL, 'b', 0, 0, "BGP-Direct"
# bgp unicast -> vnc
ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, "BGP2VNC"
ZEBRA_ROUTE_BABEL, babel, babeld, 'A', 1, 1, "Babel"
+ZEBRA_ROUTE_SHARP, sharp, sharpd, 'D', 1, 1, "SHARP"
ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, "-"
@@ -101,3 +102,4 @@ ZEBRA_ROUTE_TABLE, "Non-main Kernel Routing Table"
ZEBRA_ROUTE_LDP, "Label Distribution Protocol (LDP)"
ZEBRA_ROUTE_VNC_DIRECT, "VNC direct (not via zebra) routes"
ZEBRA_ROUTE_BABEL, "Babel routing protocol (Babel)"
+ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)"
diff --git a/lib/zclient.c b/lib/zclient.c
index 6d6d44fb12..655e4e1a80 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -52,8 +52,11 @@ socklen_t zclient_addr_len;
/* This file local debug flag. */
int zclient_debug = 0;
+struct zclient_options zclient_options_default = { .receive_notify = false };
+
/* Allocate zclient structure. */
-struct zclient *zclient_new(struct thread_master *master)
+struct zclient *zclient_new_notify(struct thread_master *master,
+ struct zclient_options *opt)
{
struct zclient *zclient;
zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
@@ -63,6 +66,8 @@ struct zclient *zclient_new(struct thread_master *master)
zclient->wb = buffer_new(0);
zclient->master = master;
+ zclient->receive_notify = opt->receive_notify;
+
return zclient;
}
@@ -190,7 +195,7 @@ void zclient_reset(struct zclient *zclient)
* @param zclient a pointer to zclient structure
* @return socket fd just to make sure that connection established
* @see zclient_init
- * @see zclient_new
+ * @see zclient_new_notify
*/
int zclient_socket_connect(struct zclient *zclient)
{
@@ -346,6 +351,11 @@ static int zebra_hello_send(struct zclient *zclient)
zclient_create_header(s, ZEBRA_HELLO, VRF_DEFAULT);
stream_putc(s, zclient->redist_default);
stream_putw(s, zclient->instance);
+ if (zclient->receive_notify)
+ stream_putc(s, 1);
+ else
+ stream_putc(s, 0);
+
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
@@ -1144,6 +1154,22 @@ stream_failure:
return 0;
}
+bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
+ enum zapi_route_notify_owner *note)
+{
+ STREAM_GET(note, s, sizeof(*note));
+
+ STREAM_GETC(s, p->family);
+ STREAM_GETC(s, p->prefixlen);
+ STREAM_GET(&p->u.prefix, s,
+ PSIZE(p->prefixlen));
+
+ return true;
+
+stream_failure:
+ return false;
+}
+
/*
* send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE
* for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will
@@ -2194,6 +2220,11 @@ static int zclient_read(struct thread *thread)
(*zclient->pw_status_update)(command, zclient, length,
vrf_id);
break;
+ case ZEBRA_ROUTE_NOTIFY_OWNER:
+ if (zclient->notify_owner)
+ (*zclient->notify_owner)(command, zclient,
+ length, vrf_id);
+ break;
default:
break;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index e9b2cb8956..de58044671 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -61,6 +61,7 @@ typedef enum {
ZEBRA_INTERFACE_SET_MASTER,
ZEBRA_ROUTE_ADD,
ZEBRA_ROUTE_DELETE,
+ ZEBRA_ROUTE_NOTIFY_OWNER,
ZEBRA_IPV4_ROUTE_ADD,
ZEBRA_IPV4_ROUTE_DELETE,
ZEBRA_IPV6_ROUTE_ADD,
@@ -137,6 +138,9 @@ struct zclient {
/* Priviledges to change socket values */
struct zebra_privs_t *privs;
+ /* Do we care about failure events for route install? */
+ bool receive_notify;
+
/* Socket to zebra daemon. */
int sock;
@@ -199,6 +203,8 @@ struct zclient {
int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t);
int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t);
int (*pw_status_update)(int, struct zclient *, uint16_t, vrf_id_t);
+ int (*notify_owner)(int command, struct zclient *zclient,
+ uint16_t length, vrf_id_t vrf_id);
};
/* Zebra API message flag. */
@@ -323,12 +329,35 @@ struct zapi_pw_status {
uint32_t status;
};
+enum zapi_route_notify_owner {
+ ZAPI_ROUTE_FAIL_INSTALL,
+ ZAPI_ROUTE_BETTER_ADMIN_WON,
+ ZAPI_ROUTE_INSTALLED,
+};
+
/* Zebra MAC types */
#define ZEBRA_MAC_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MAC_TYPE_GW 0x02 /* gateway (SVI) mac*/
+struct zclient_options {
+ bool receive_notify;
+};
+
/* Prototypes of zebra client service functions. */
extern struct zclient *zclient_new(struct thread_master *);
+
+#if CONFDATE > 20181101
+CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
+#endif
+
+extern struct zclient_options zclient_options_default;
+
+extern struct zclient *zclient_new_notify(struct thread_master *m,
+ struct zclient_options *opt);
+
+#define zclient_new(A) zclient_new_notify((A), &zclient_options_default); \
+ CPP_WARN("Please transition to using zclient_new_notify");
+
extern void zclient_init(struct zclient *, int, u_short, struct zebra_privs_t *privs);
extern int zclient_start(struct zclient *);
extern void zclient_stop(struct zclient *);
@@ -445,6 +474,8 @@ extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *,
extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *);
extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *);
extern int zapi_route_decode(struct stream *, struct zapi_route *);
+bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
+ enum zapi_route_notify_owner *note);
static inline void zapi_route_set_blackhole(struct zapi_route *api,
enum blackhole_type bh_type)
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 7701dcbb88..2612d8e045 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -314,7 +314,7 @@ void nhrp_zebra_init(void)
zebra_rib[AFI_IP] = route_table_init();
zebra_rib[AFI_IP6] = route_table_init();
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient->zebra_connected = nhrp_zebra_connected;
zclient->interface_add = nhrp_interface_add;
zclient->interface_delete = nhrp_interface_delete;
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 6bbab46ad8..bd5e2bd1d3 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -61,8 +61,8 @@ static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa)
case OSPF6_LSTYPE_ROUTER:
case OSPF6_LSTYPE_NETWORK:
if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) {
- zlog_debug("Examin %s", lsa->name);
- zlog_debug("Schedule SPF Calculation for %s",
+ zlog_debug("%s Examin LSA %s", __PRETTY_FUNCTION__, lsa->name);
+ zlog_debug(" Schedule SPF Calculation for %s",
OSPF6_AREA(lsa->lsdb->data)->name);
}
ospf6_spf_schedule(
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index b5a0a9209b..b1d940952c 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1316,7 +1316,7 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
return;
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
- zlog_debug("%s found", lsa->name);
+ zlog_debug("%s: LSA %s found", __PRETTY_FUNCTION__, lsa->name);
oa = OSPF6_AREA(lsa->lsdb->data);
@@ -1325,7 +1325,7 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
lsa->header);
if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER))
ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
- htonl(0), &ls_prefix);
+ intra_prefix_lsa->ref_id, &ls_prefix);
else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
intra_prefix_lsa->ref_id, &ls_prefix);
@@ -1404,7 +1404,7 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf, sizeof(buf));
- zlog_debug(" add %s", buf);
+ zlog_debug(" route %s add", buf);
}
ospf6_route_add(route, oa->route_table);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 4276f46c38..340d90159f 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -110,26 +110,30 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
sizeof(struct ospf6_vertex));
/* type */
- if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER)
+ if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
v->type = OSPF6_VERTEX_TYPE_ROUTER;
- else if (ntohs(lsa->header->type) == OSPF6_LSTYPE_NETWORK)
+ /* Router LSA use Link ID 0 as base in vertex_id */
+ ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0),
+ &v->vertex_id);
+ } else if (ntohs(lsa->header->type) == OSPF6_LSTYPE_NETWORK) {
v->type = OSPF6_VERTEX_TYPE_NETWORK;
- else
- assert(0);
-
- /* vertex_id */
- ospf6_linkstate_prefix(lsa->header->adv_router, lsa->header->id,
+ /* vertex_id */
+ ospf6_linkstate_prefix(lsa->header->adv_router, lsa->header->id,
&v->vertex_id);
+ } else
+ assert(0);
/* name */
ospf6_linkstate_prefix2str(&v->vertex_id, v->name, sizeof(v->name));
if (IS_OSPF6_DEBUG_SPF(PROCESS))
- zlog_debug("%s: Creating vertex %s of type %s", __func__,
- v->name,
+ zlog_debug("%s: Creating vertex %s of type %s (0x%04hx) lsa %s",
+ __func__, v->name,
((ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER)
? "Router"
- : "N/W"));
+ : "N/W"), ntohs(lsa->header->type),
+ lsa->name);
+
/* Associated LSA */
v->lsa = lsa;
@@ -158,7 +162,8 @@ static void ospf6_vertex_delete(struct ospf6_vertex *v)
}
static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
- struct ospf6_vertex *v)
+ struct ospf6_vertex *v,
+ uint32_t link_id)
{
struct ospf6_lsa *lsa;
u_int16_t type = 0;
@@ -166,12 +171,12 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
if (VERTEX_IS_TYPE(NETWORK, v)) {
type = htons(OSPF6_LSTYPE_ROUTER);
- id = htonl(0);
+ id = link_id;
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else {
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
type = htons(OSPF6_LSTYPE_ROUTER);
- id = htonl(0);
+ id = link_id;
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
type = htons(OSPF6_LSTYPE_NETWORK);
@@ -187,10 +192,12 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
if (lsa)
- zlog_debug(" Link to: %s", lsa->name);
+ zlog_debug(" Link to: %s , V %s id %u", lsa->name,
+ v->name, link_id);
else
- zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA",
- ospf6_lstype_name(type), ibuf, abuf);
+ zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s id %u",
+ ospf6_lstype_name(type), ibuf, abuf,
+ v->name, link_id);
}
return lsa;
@@ -308,10 +315,11 @@ static int ospf6_spf_install(struct ospf6_vertex *v,
{
struct ospf6_route *route, *parent_route;
struct ospf6_vertex *prev;
+ char pbuf[PREFIX2STR_BUFFER];
if (IS_OSPF6_DEBUG_SPF(PROCESS))
- zlog_debug("SPF install %s hops %d cost %d", v->name, v->hops,
- v->cost);
+ zlog_debug("SPF install %s (lsa %s) hops %d cost %d", v->name,
+ v->lsa->name, v->hops, v->cost);
route = ospf6_route_lookup(&v->vertex_id, result_table);
if (route && route->path.cost < v->cost) {
@@ -322,16 +330,30 @@ static int ospf6_spf_install(struct ospf6_vertex *v,
ospf6_vertex_delete(v);
return -1;
} else if (route && route->path.cost == v->cost) {
- if (IS_OSPF6_DEBUG_SPF(PROCESS))
- zlog_debug(" another path found, merge");
-
+ if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
+ prefix2str(&route->prefix, pbuf, sizeof(pbuf));
+ zlog_debug(" another path found to route %s lsa %s, merge",
+ pbuf, v->lsa->name);
+ }
ospf6_spf_merge_nexthops_to_route(route, v);
prev = (struct ospf6_vertex *)route->route_option;
assert(prev->hops <= v->hops);
- ospf6_vertex_delete(v);
+ if ((VERTEX_IS_TYPE(ROUTER, v) &&
+ route->path.origin.id != v->lsa->header->id)) {
+ if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
+ zlog_debug("%s: V lsa %s id %u, route id %u are different",
+ __PRETTY_FUNCTION__, v->lsa->name,
+ ntohl(v->lsa->header->id),
+ ntohl(route->path.origin.id));
+ }
+ return 0;
+ }
+
+ ospf6_vertex_delete(v);
return -1;
+
}
/* There should be no case where candidate being installed (variable
@@ -438,8 +460,10 @@ void ospf6_spf_calculation(u_int32_t router_id,
struct ospf6_vertex *root, *v, *w;
int size;
caddr_t lsdesc;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *self_rtr_lsa = NULL, *rtr_lsa = NULL;
+ const struct route_node *end = NULL;
struct in6_addr address;
+ struct ospf6_lsdb *lsdb = NULL;
ospf6_spf_table_finish(result_table);
@@ -454,6 +478,8 @@ void ospf6_spf_calculation(u_int32_t router_id,
return;
}
+ self_rtr_lsa = lsa;
+
/* initialize */
candidate_list = pqueue_create();
candidate_list->cmp = ospf6_vertex_cmp;
@@ -462,6 +488,7 @@ void ospf6_spf_calculation(u_int32_t router_id,
root->area = oa;
root->cost = 0;
root->hops = 0;
+ root->link_id = lsa->header->id;
inet_pton(AF_INET6, "::1", &address);
/* Actually insert root to the candidate-list as the only candidate */
@@ -482,55 +509,134 @@ void ospf6_spf_calculation(u_int32_t router_id,
&& ospf6_router_is_stub_router(v->lsa)))
continue;
- /* For each LS description in the just-added vertex V's LSA */
- size = (VERTEX_IS_TYPE(ROUTER, v)
- ? sizeof(struct ospf6_router_lsdesc)
- : sizeof(struct ospf6_network_lsdesc));
- for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
- lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
- lsdesc += size) {
- lsa = ospf6_lsdesc_lsa(lsdesc, v);
- if (lsa == NULL)
- continue;
-
- if (OSPF6_LSA_IS_MAXAGE(lsa))
- continue;
-
- if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
- continue;
-
- w = ospf6_vertex_create(lsa);
- w->area = oa;
- w->parent = v;
- if (VERTEX_IS_TYPE(ROUTER, v)) {
- w->cost = v->cost
- + ROUTER_LSDESC_GET_METRIC(lsdesc);
- w->hops =
- v->hops
- + (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
- } else /* NETWORK */
- {
- w->cost = v->cost;
- w->hops = v->hops + 1;
+ if (VERTEX_IS_TYPE(ROUTER, v)) {
+ /* First fetch root Router LSAs from lsdb_self */
+ if (v->lsa == self_rtr_lsa)
+ lsdb = oa->lsdb_self;
+ else
+ lsdb = v->area->lsdb;
+
+ /* Iterating multiple ROUTER LSAs from same adv router
+ * with different Link State ID */
+ end = ospf6_lsdb_head(lsdb, 2,
+ htons(OSPF6_LSTYPE_ROUTER),
+ v->lsa->header->adv_router,
+ &rtr_lsa);
+ while (rtr_lsa) {
+ if (IS_OSPF6_DEBUG_SPF(PROCESS))
+ zlog_debug("%s: Next LSA %s to process"
+ ,__PRETTY_FUNCTION__,
+ rtr_lsa->name);
+ size = sizeof(struct ospf6_router_lsdesc);
+ /* For each LS description in the just-added vertex V's LSA */
+ for (lsdesc = OSPF6_LSA_HEADER_END(
+ rtr_lsa->header) + 4;
+ lsdesc + size <= OSPF6_LSA_END(
+ rtr_lsa->header);
+ lsdesc += size) {
+ lsa = ospf6_lsdesc_lsa(lsdesc, v,
+ rtr_lsa->header->id);
+ if (lsa == NULL)
+ continue;
+
+ if (OSPF6_LSA_IS_MAXAGE(lsa))
+ continue;
+
+ if (!ospf6_lsdesc_backlink(lsa,
+ lsdesc, v))
+ continue;
+
+ w = ospf6_vertex_create(lsa);
+ w->area = oa;
+ w->parent = v;
+ w->link_id = rtr_lsa->header->id;
+
+ if (VERTEX_IS_TYPE(ROUTER, v)) {
+ w->cost = v->cost
+ + ROUTER_LSDESC_GET_METRIC(lsdesc);
+ w->hops =
+ v->hops
+ + (VERTEX_IS_TYPE(NETWORK, w)
+ ? 0 : 1);
+ } else /* NETWORK */ {
+ w->cost = v->cost;
+ w->hops = v->hops + 1;
+ }
+
+ /* nexthop calculation */
+ if (w->hops == 0)
+ ospf6_add_nexthop(w->nh_list,
+ ROUTER_LSDESC_GET_IFID(lsdesc)
+ , NULL);
+ else if (w->hops == 1 && v->hops == 0)
+ ospf6_nexthop_calc(w, v, lsdesc);
+ else {
+ ospf6_copy_nexthops(w->nh_list,
+ v->nh_list);
+ }
+
+ /* add new candidate to the candidate_list */
+ if (IS_OSPF6_DEBUG_SPF(PROCESS))
+ zlog_debug(
+ " New candidate: %s hops %d cost %d",
+ w->name, w->hops,
+ w->cost);
+ pqueue_enqueue(w, candidate_list);
+ }
+ /* Fetch next Link state ID Router LSA */
+ rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
}
-
- /* nexthop calculation */
- if (w->hops == 0)
- ospf6_add_nexthop(
- w->nh_list,
+ } else {
+ /* For each LS description in the just-added vertex V's LSA */
+ size = (VERTEX_IS_TYPE(ROUTER, v)
+ ? sizeof(struct ospf6_router_lsdesc)
+ : sizeof(struct ospf6_network_lsdesc));
+ for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
+ lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
+ lsdesc += size) {
+ lsa = ospf6_lsdesc_lsa(lsdesc, v, v->link_id);
+ if (lsa == NULL)
+ continue;
+
+ if (OSPF6_LSA_IS_MAXAGE(lsa))
+ continue;
+
+ if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
+ continue;
+
+ w = ospf6_vertex_create(lsa);
+ w->area = oa;
+ w->parent = v;
+ if (VERTEX_IS_TYPE(ROUTER, v)) {
+ w->cost = v->cost
+ + ROUTER_LSDESC_GET_METRIC(lsdesc);
+ w->hops =
+ v->hops
+ + (VERTEX_IS_TYPE(NETWORK, w) ?
+ 0 : 1);
+ } else /* NETWORK */ {
+ w->cost = v->cost;
+ w->hops = v->hops + 1;
+ }
+
+ /* nexthop calculation */
+ if (w->hops == 0)
+ ospf6_add_nexthop(w->nh_list,
ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
- else if (w->hops == 1 && v->hops == 0)
- ospf6_nexthop_calc(w, v, lsdesc);
- else {
- ospf6_copy_nexthops(w->nh_list, v->nh_list);
- }
-
- /* add new candidate to the candidate_list */
- if (IS_OSPF6_DEBUG_SPF(PROCESS))
- zlog_debug(
+ else if (w->hops == 1 && v->hops == 0)
+ ospf6_nexthop_calc(w, v, lsdesc);
+ else {
+ ospf6_copy_nexthops(w->nh_list,
+ v->nh_list);
+ }
+
+ /* add new candidate to the candidate_list */
+ if (IS_OSPF6_DEBUG_SPF(PROCESS))
+ zlog_debug(
" New candidate: %s hops %d cost %d",
- w->name, w->hops, w->cost);
- pqueue_enqueue(w, candidate_list);
+ w->name, w->hops, w->cost);
+ pqueue_enqueue(w, candidate_list);
+ }
}
}
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index 2246e2dfc7..dbb88d12ba 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -68,6 +68,7 @@ struct ospf6_vertex {
/* nexthops to this node */
struct list *nh_list;
+ uint32_t link_id;
};
#define OSPF6_VERTEX_TYPE_ROUTER 0x01
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index a900648236..cc87c499ee 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -583,7 +583,7 @@ static void ospf6_zebra_connected(struct zclient *zclient)
void ospf6_zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
zclient->zebra_connected = ospf6_zebra_connected;
zclient->router_id_update = ospf6_router_id_update_zebra;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index f8537a4abd..f1848f1eaf 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -201,6 +201,9 @@ DEFUN_NOSH (router_ospf,
struct ospf *ospf = NULL;
int ret = CMD_SUCCESS;
u_short instance = 0;
+ struct vrf *vrf = NULL;
+ struct route_node *rn;
+ struct interface *ifp;
ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance);
if (!ospf)
@@ -219,6 +222,34 @@ DEFUN_NOSH (router_ospf,
instance, ospf->name ? ospf->name : "NIL",
ospf->vrf_id, ospf->oi_running);
VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
+
+ /* Activate 'ip ospf area x' configured interfaces for given
+ * vrf. Activate area on vrf x aware interfaces.
+ * vrf_enable callback calls router_id_update which
+ * internally will call ospf_if_update to trigger
+ * network_run_state
+ */
+ vrf = vrf_lookup_by_id(ospf->vrf_id);
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct ospf_if_params *params;
+
+ params = IF_DEF_PARAMS(ifp);
+ if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
+ for (rn = route_top(ospf->networks); rn;
+ rn = route_next(rn)) {
+ if (rn->info != NULL) {
+ vty_out(vty,
+ "Interface %s has area config but please remove all network commands first.\n",
+ ifp->name);
+ return ret;
+ }
+ }
+ ospf_interface_area_set(ospf, ifp);
+ ospf->if_ospf_cli_count++;
+ }
+ }
+
ospf_router_id_update(ospf);
}
@@ -570,6 +601,11 @@ DEFUN (ospf_network_area,
if (ospf->if_ospf_cli_count > 0) {
vty_out(vty,
"Please remove all ip ospf area x.x.x.x commands first.\n");
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s ospf vrf %s num of %u ip osp area x config",
+ __PRETTY_FUNCTION__,
+ ospf->name ? ospf->name : "NIL",
+ ospf->if_ospf_cli_count);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -7926,7 +7962,7 @@ DEFUN (ip_ospf_area,
else
ospf = ospf_lookup_instance(instance);
- if (ospf == NULL) {
+ if (instance && ospf == NULL) {
params = IF_DEF_PARAMS(ifp);
if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
UNSET_IF_PARAM(params, if_area);
@@ -7971,11 +8007,13 @@ DEFUN (ip_ospf_area,
ospf_if_update_params((ifp), (addr));
}
- for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) {
- if (rn->info != NULL) {
- vty_out(vty,
- "Please remove all network commands first.\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (ospf) {
+ for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) {
+ if (rn->info != NULL) {
+ vty_out(vty,
+ "Please remove all network commands first.\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
}
}
@@ -7985,8 +8023,11 @@ DEFUN (ip_ospf_area,
params->if_area = area_id;
params->if_area_id_fmt = format;
}
- ospf_interface_area_set(ospf, ifp);
- ospf->if_ospf_cli_count++;
+
+ if (ospf) {
+ ospf_interface_area_set(ospf, ifp);
+ ospf->if_ospf_cli_count++;
+ }
return CMD_SUCCESS;
}
@@ -8828,188 +8869,438 @@ static void config_write_stub_router(struct vty *vty, struct ospf *ospf)
}
static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf,
- struct route_table *rt)
+ struct route_table *rt,
+ json_object *json)
{
struct route_node *rn;
struct ospf_route * or ;
struct listnode *pnode, *pnnode;
struct ospf_path *path;
+ json_object *json_route = NULL, *json_nexthop_array = NULL,
+ *json_nexthop = NULL;
- vty_out(vty, "============ OSPF network routing table ============\n");
+ if (!json)
+ vty_out(vty, "============ OSPF network routing table ============\n");
- for (rn = route_top(rt); rn; rn = route_next(rn))
- if ((or = rn->info) != NULL) {
- char buf1[19];
- snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4),
- rn->p.prefixlen);
-
- switch (or->path_type) {
- case OSPF_PATH_INTER_AREA:
- if (or->type == OSPF_DESTINATION_NETWORK)
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ if ((or = rn->info) == NULL)
+ continue;
+ char buf1[PREFIX2STR_BUFFER];
+
+ memset(buf1, 0, sizeof(buf1));
+ prefix2str(&rn->p, buf1, sizeof(buf1));
+
+ json_route = json_object_new_object();
+ if (json) {
+ json_object_object_add(json, buf1, json_route);
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_NOSLASHESCAPE);
+
+ }
+
+ switch (or->path_type) {
+ case OSPF_PATH_INTER_AREA:
+ if (or->type == OSPF_DESTINATION_NETWORK) {
+ if (json) {
+ json_object_string_add(json_route,
+ "routeType",
+ "N IA");
+ json_object_int_add(json_route,
+ "cost",
+ or->cost);
+ json_object_string_add(
+ json_route,
+ "area",
+ inet_ntoa(
+ or->u.std.area_id));
+ } else {
vty_out(vty,
- "N IA %-18s [%d] area: %s\n",
+ "N IA %-18s [%d] area: %s\n",
buf1, or->cost,
- inet_ntoa(or->u.std.area_id));
- else if (or->type == OSPF_DESTINATION_DISCARD)
+ inet_ntoa(or->u.std.area_id));
+ }
+ } else if (or->type ==
+ OSPF_DESTINATION_DISCARD) {
+ if (json) {
+ json_object_string_add(json_route,
+ "routeType",
+ "D IA");
+ } else {
vty_out(vty,
"D IA %-18s Discard entry\n",
buf1);
- break;
- case OSPF_PATH_INTRA_AREA:
+ }
+ }
+ break;
+ case OSPF_PATH_INTRA_AREA:
+ if (json) {
+ json_object_string_add(json_route,
+ "routeType", "N");
+ json_object_int_add(json_route, "cost",
+ or->cost);
+ json_object_string_add(json_route,
+ "area", inet_ntoa(or->u.std.area_id));
+ } else {
vty_out(vty, "N %-18s [%d] area: %s\n",
buf1, or->cost,
inet_ntoa(or->u.std.area_id));
- break;
- default:
- break;
}
+ break;
+ default:
+ break;
+ }
- if (or->type == OSPF_DESTINATION_NETWORK)
- for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode,
- path)) {
- if (if_lookup_by_index(path->ifindex,
- ospf->vrf_id)) {
- if (path->nexthop.s_addr == 0)
- vty_out(vty,
- "%24s directly attached to %s\n",
- "",
+ if (or->type == OSPF_DESTINATION_NETWORK) {
+ if (json) {
+ json_nexthop_array = json_object_new_array();
+ json_object_object_add(json_route, "nexthops",
+ json_nexthop_array);
+ }
+
+ for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode,
+ path)) {
+ if (json) {
+ json_nexthop =
+ json_object_new_object();
+ json_object_array_add(json_nexthop_array,
+ json_nexthop);
+ }
+ if (if_lookup_by_index(path->ifindex,
+ ospf->vrf_id)) {
+
+ if (path->nexthop.s_addr == 0) {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
+ " ");
+ json_object_string_add(
+ json_nexthop,
+ "directly attached to",
ifindex2ifname(
- path->ifindex,
- ospf->vrf_id));
- else
+ path->ifindex,
+ ospf->vrf_id));
+ } else {
vty_out(vty,
- "%24s via %s, %s\n",
- "",
+ "%24s directly attached to %s\n",
+ "",
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
+ } else {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
inet_ntoa(
- path->nexthop),
+ path->nexthop));
+ json_object_string_add(
+ json_nexthop,
+ "via",
ifindex2ifname(
- path->ifindex,
- ospf->vrf_id));
+ path->ifindex,
+ ospf->vrf_id));
+ } else {
+ vty_out(vty,
+ "%24s via %s, %s\n",
+ "",
+ inet_ntoa(
+ path->nexthop),
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
}
}
+ }
}
- vty_out(vty, "\n");
+ if (!json)
+ json_object_free(json_route);
+ }
+ if (!json)
+ vty_out(vty, "\n");
}
static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf,
- struct route_table *rtrs)
+ struct route_table *rtrs,
+ json_object *json)
{
struct route_node *rn;
struct ospf_route * or ;
struct listnode *pnode;
struct listnode *node;
struct ospf_path *path;
+ json_object *json_route = NULL, *json_nexthop_array = NULL,
+ *json_nexthop = NULL;
- vty_out(vty, "============ OSPF router routing table =============\n");
- for (rn = route_top(rtrs); rn; rn = route_next(rn))
- if (rn->info) {
- int flag = 0;
+ if (!json)
+ vty_out(vty, "============ OSPF router routing table =============\n");
+
+ for (rn = route_top(rtrs); rn; rn = route_next(rn)) {
+ if (rn->info == NULL)
+ continue;
+ int flag = 0;
+ json_route = json_object_new_object();
+ if (json) {
+ json_object_object_add(json,
+ inet_ntoa(rn->p.u.prefix4),
+ json_route);
+ json_object_string_add(json_route, "routeType",
+ "R ");
+ } else {
vty_out(vty, "R %-15s ",
inet_ntoa(rn->p.u.prefix4));
+ }
- for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
- or)) {
- if (flag++)
+ for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node,
+ or)) {
+ if (flag++) {
+ if (!json)
vty_out(vty, "%24s", "");
+ }
- /* Show path. */
+ /* Show path. */
+ if (json) {
+ json_object_int_add(json_route, "cost",
+ or->cost);
+ json_object_string_add(json_route,
+ "area",
+ inet_ntoa(or->u.std.area_id));
+ if (or->path_type ==
+ OSPF_PATH_INTER_AREA)
+ json_object_boolean_true_add(
+ json_route,
+ "IA");
+ if (or->u.std.flags & ROUTER_LSA_BORDER)
+ json_object_string_add(
+ json_route,
+ "routerType",
+ "abr");
+ else if (or->u.std.flags &
+ ROUTER_LSA_EXTERNAL)
+ json_object_string_add(
+ json_route,
+ "routerType",
+ "asbr");
+ } else {
vty_out(vty, "%s [%d] area: %s",
- (or->path_type == OSPF_PATH_INTER_AREA
- ? "IA"
- : " "),
- or->cost, inet_ntoa(or->u.std.area_id));
+ (or->path_type == OSPF_PATH_INTER_AREA
+ ? "IA"
+ : " "),
+ or->cost, inet_ntoa(or->u.std.area_id));
/* Show flags. */
vty_out(vty, "%s%s\n",
- (or->u.std.flags & ROUTER_LSA_BORDER
- ? ", ABR"
- : ""),
- (or->u.std.flags & ROUTER_LSA_EXTERNAL
- ? ", ASBR"
- : ""));
-
- for (ALL_LIST_ELEMENTS_RO(or->paths, pnode,
- path)) {
- if (if_lookup_by_index(path->ifindex,
- ospf->vrf_id)) {
- if (path->nexthop.s_addr == 0)
- vty_out(vty,
- "%24s directly attached to %s\n",
- "",
+ (or->u.std.flags & ROUTER_LSA_BORDER
+ ? ", ABR"
+ : ""),
+ (or->u.std.flags & ROUTER_LSA_EXTERNAL
+ ? ", ASBR"
+ : ""));
+ }
+
+ if (json) {
+ json_nexthop_array =
+ json_object_new_array();
+ json_object_object_add(json_route, "nexthops",
+ json_nexthop_array);
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(or->paths, pnode,
+ path)) {
+ if (json) {
+ json_nexthop =
+ json_object_new_object();
+ json_object_array_add(
+ json_nexthop_array,
+ json_nexthop);
+ }
+ if (if_lookup_by_index(path->ifindex,
+ ospf->vrf_id)) {
+ if (path->nexthop.s_addr == 0) {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
+ " ");
+ json_object_string_add(
+ json_nexthop,
+ "directly attached to",
ifindex2ifname(
path->ifindex,
ospf->vrf_id));
- else
+ } else {
vty_out(vty,
- "%24s via %s, %s\n",
- "",
- inet_ntoa(
- path->nexthop),
+ "%24s directly attached to %s\n",
+ "",
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
+ } else {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
+ inet_ntoa(path->nexthop));
+ json_object_string_add(
+ json_nexthop,
+ "via",
ifindex2ifname(
path->ifindex,
ospf->vrf_id));
+ } else {
+ vty_out(vty,
+ "%24s via %s, %s\n",
+ "",
+ inet_ntoa(
+ path->nexthop),
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
}
}
}
}
- vty_out(vty, "\n");
+ if (!json)
+ json_object_free(json_route);
+ }
+ if (!json)
+ vty_out(vty, "\n");
}
static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf,
- struct route_table *rt)
+ struct route_table *rt,
+ json_object *json)
{
struct route_node *rn;
struct ospf_route *er;
struct listnode *pnode, *pnnode;
struct ospf_path *path;
+ json_object *json_route = NULL, *json_nexthop_array = NULL,
+ *json_nexthop = NULL;
- vty_out(vty, "============ OSPF external routing table ===========\n");
- for (rn = route_top(rt); rn; rn = route_next(rn))
- if ((er = rn->info) != NULL) {
- char buf1[19];
- snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4),
- rn->p.prefixlen);
+ if (!json)
+ vty_out(vty, "============ OSPF external routing table ===========\n");
+
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ if ((er = rn->info) == NULL)
+ continue;
+
+ char buf1[19];
+
+ snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4),
+ rn->p.prefixlen);
+ json_route = json_object_new_object();
+ if (json) {
+ json_object_object_add(json, buf1, json_route);
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_NOSLASHESCAPE);
- switch (er->path_type) {
- case OSPF_PATH_TYPE1_EXTERNAL:
+ }
+
+ switch (er->path_type) {
+ case OSPF_PATH_TYPE1_EXTERNAL:
+ if (json) {
+ json_object_string_add(json_route,
+ "routeType",
+ "N E1");
+ json_object_int_add(json_route, "cost",
+ er->cost);
+ } else {
vty_out(vty,
- "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI
- "\n",
- buf1, er->cost, er->u.ext.tag);
- break;
- case OSPF_PATH_TYPE2_EXTERNAL:
+ "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI
+ "\n",
+ buf1, er->cost, er->u.ext.tag);
+ }
+ break;
+ case OSPF_PATH_TYPE2_EXTERNAL:
+ if (json) {
+ json_object_string_add(json_route,
+ "routeType",
+ "N E2");
+ json_object_int_add(json_route, "cost",
+ er->cost);
+ } else {
vty_out(vty,
- "N E2 %-18s [%d/%d] tag: %" ROUTE_TAG_PRI
- "\n",
- buf1, er->cost, er->u.ext.type2_cost,
+ "N E2 %-18s [%d/%d] tag: %"
+ ROUTE_TAG_PRI
+ "\n", buf1, er->cost,
+ er->u.ext.type2_cost,
er->u.ext.tag);
- break;
}
+ break;
+ }
- for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode,
- path)) {
- if (if_lookup_by_index(path->ifindex,
- ospf->vrf_id)) {
- if (path->nexthop.s_addr == 0)
- vty_out(vty,
- "%24s directly attached to %s\n",
- "",
+ if (json) {
+ json_nexthop_array = json_object_new_array();
+ json_object_object_add(json_route, "nexthops",
+ json_nexthop_array);
+ }
+
+ for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode,
+ path)) {
+ if (json) {
+ json_nexthop = json_object_new_object();
+ json_object_array_add(json_nexthop_array
+ ,json_nexthop);
+ }
+
+ if (if_lookup_by_index(path->ifindex,
+ ospf->vrf_id)) {
+ if (path->nexthop.s_addr == 0) {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
+ " ");
+ json_object_string_add(
+ json_nexthop,
+ "directly attached to",
ifindex2ifname(
- path->ifindex,
- ospf->vrf_id));
- else
+ path->ifindex,
+ ospf->vrf_id));
+ } else {
vty_out(vty,
- "%24s via %s, %s\n",
- "",
+ "%24s directly attached to %s\n",
+ "",
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
+ } else {
+ if (json) {
+ json_object_string_add(
+ json_nexthop,
+ "ip",
inet_ntoa(
- path->nexthop),
+ path->nexthop));
+ json_object_string_add(
+ json_nexthop,
+ "via",
ifindex2ifname(
- path->ifindex,
- ospf->vrf_id));
+ path->ifindex,
+ ospf->vrf_id));
+ } else {
+ vty_out(vty,
+ "%24s via %s, %s\n",
+ "",
+ inet_ntoa(
+ path->nexthop),
+ ifindex2ifname(
+ path->ifindex,
+ ospf->vrf_id));
+ }
}
}
}
- vty_out(vty, "\n");
+ if (!json)
+ json_object_free(json_route);
+ }
+ if (!json)
+ vty_out(vty, "\n");
}
static int show_ip_ospf_border_routers_common(struct vty *vty,
@@ -9030,7 +9321,7 @@ static int show_ip_ospf_border_routers_common(struct vty *vty,
show_ip_ospf_route_network (vty, ospf->new_table); */
/* Show Router routes. */
- show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs);
+ show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, NULL);
vty_out(vty, "\n");
@@ -9113,12 +9404,22 @@ DEFUN (show_ip_ospf_instance_border_routers,
}
static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf,
- u_char use_vrf)
+ json_object *json, u_char use_vrf)
{
+ json_object *json_vrf = NULL;
+
if (ospf->instance)
vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance);
- ospf_show_vrf_name(ospf, vty, NULL, use_vrf);
+
+ if (json) {
+ if (use_vrf)
+ json_vrf = json_object_new_object();
+ else
+ json_vrf = json;
+ }
+
+ ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (ospf->new_table == NULL) {
vty_out(vty, "No OSPF routing information exist\n");
@@ -9126,28 +9427,42 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf,
}
/* Show Network routes. */
- show_ip_ospf_route_network(vty, ospf, ospf->new_table);
+ show_ip_ospf_route_network(vty, ospf, ospf->new_table, json_vrf);
/* Show Router routes. */
- show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs);
+ show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, json_vrf);
/* Show AS External routes. */
- show_ip_ospf_route_external(vty, ospf, ospf->old_external_route);
+ show_ip_ospf_route_external(vty, ospf, ospf->old_external_route,
+ json_vrf);
- vty_out(vty, "\n");
+ if (json) {
+ if (use_vrf) {
+ //json_object_object_add(json_vrf, "areas", json_areas);
+ if (ospf->vrf_id == VRF_DEFAULT)
+ json_object_object_add(json, "default",
+ json_vrf);
+ else
+ json_object_object_add(json, ospf->name,
+ json_vrf);
+ }
+ } else {
+ vty_out(vty, "\n");
+ }
return CMD_SUCCESS;
}
DEFUN (show_ip_ospf_route,
show_ip_ospf_route_cmd,
- "show ip ospf [vrf <NAME|all>] route",
+ "show ip ospf [vrf <NAME|all>] route [json]",
SHOW_STR
IP_STR
"OSPF information\n"
VRF_CMD_HELP_STR
"All VRFs\n"
- "OSPF routing table\n")
+ "OSPF routing table\n"
+ JSON_STR)
{
struct ospf *ospf = NULL;
struct listnode *node = NULL;
@@ -9157,6 +9472,11 @@ DEFUN (show_ip_ospf_route,
int inst = 0;
int idx_vrf = 0;
u_char use_vrf = 0;
+ u_char uj = use_json(argc, argv);
+ json_object *json = NULL;
+
+ if (uj)
+ json = json_object_new_object();
OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
@@ -9167,23 +9487,44 @@ DEFUN (show_ip_ospf_route,
for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
if (!ospf->oi_running)
continue;
- ret = show_ip_ospf_route_common(vty, ospf,
+ ret = show_ip_ospf_route_common(vty, ospf, json,
use_vrf);
}
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+
return ret;
}
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
- if (ospf == NULL || !ospf->oi_running)
+ if (ospf == NULL || !ospf->oi_running) {
+ if (uj)
+ json_object_free(json);
return CMD_SUCCESS;
+ }
} else {
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (ospf == NULL || !ospf->oi_running)
+ if (ospf == NULL || !ospf->oi_running) {
+ if (uj)
+ json_object_free(json);
return CMD_SUCCESS;
+ }
+ }
+
+ if (ospf) {
+ ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf);
+ if (uj)
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
}
- if (ospf)
- ret = show_ip_ospf_route_common(vty, ospf, use_vrf);
+ if (uj)
+ json_object_free(json);
return ret;
}
@@ -9209,7 +9550,7 @@ DEFUN (show_ip_ospf_instance_route,
if (!ospf->oi_running)
return CMD_SUCCESS;
- return show_ip_ospf_route_common(vty, ospf, 0);
+ return show_ip_ospf_route_common(vty, ospf, NULL, 0);
}
@@ -10064,7 +10405,14 @@ static int ospf_config_write(struct vty *vty)
return write;
for (ALL_LIST_ELEMENTS_RO(om->ospf, ospf_node, ospf)) {
- if (ospf->oi_running)
+ /* VRF Default check if it is running.
+ * Upon daemon start, there could be default instance
+ * in absence of 'router ospf'/oi_running is disabled. */
+ if (ospf->vrf_id == VRF_DEFAULT && ospf->oi_running)
+ write += ospf_config_write_one(vty, ospf);
+ /* For Non-Default VRF simply display the configuration,
+ * even if it is not oi_running. */
+ else if (ospf->vrf_id != VRF_DEFAULT)
write += ospf_config_write_one(vty, ospf);
}
return write;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 34ad6f65b0..66be29dbb4 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1475,7 +1475,7 @@ static void ospf_zebra_connected(struct zclient *zclient)
void ospf_zebra_init(struct thread_master *master, u_short instance)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);
zclient->zebra_connected = ospf_zebra_connected;
zclient->router_id_update = ospf_router_id_update_zebra;
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index bd3be06646..5cb8ca85bc 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -300,7 +300,9 @@ struct ospf {
/* Statistics for LSA used for new instantiation. */
u_int32_t rx_lsa_count;
- /* Counter of "ip ospf area x.x.x.x" */
+ /* Counter of "ip ospf area x.x.x.x" used
+ * for multual exclusion of network command under
+ * router ospf or ip ospf area x under interface. */
u_int32_t if_ospf_cli_count;
struct route_table *distance_table;
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 04466258bb..689e9a7449 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -748,7 +748,7 @@ void pim_zebra_init(void)
int i;
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient->zebra_connected = pim_zebra_connected;
zclient->router_id_update = pim_router_id_update_zebra;
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index fd75a699b3..bcaf4a38dd 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -120,7 +120,7 @@ void zclient_lookup_free(void)
void zclient_lookup_new(void)
{
- zlookup = zclient_new(master);
+ zlookup = zclient_new_notify(master, &zclient_options_default);
if (!zlookup) {
zlog_err("%s: zclient_new() failure", __PRETTY_FUNCTION__);
return;
diff --git a/redhat/daemons b/redhat/daemons
index c163f4d2ce..889e288e57 100644
--- a/redhat/daemons
+++ b/redhat/daemons
@@ -49,6 +49,7 @@ pimd=no
nhrpd=no
eigrpd=no
babeld=no
+sharpd=no
#
# Command line options for the daemons
#
@@ -64,6 +65,7 @@ pimd_options=("-A 127.0.0.1")
nhrpd_options=("-A 127.0.0.1")
eigrpd_options=("-A 127.0.0.1")
babeld_options=("-A 127.0.0.1")
+sharpd_options=("-A 127.0.0.1")
#
# If the vtysh_enable is yes, then the unified config is read
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index e479e2474d..041635e153 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -590,7 +590,7 @@ static void rip_zebra_connected(struct zclient *zclient)
void rip_zclient_init(struct thread_master *master)
{
/* Set default value to the zebra client structure. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
zclient->zebra_connected = rip_zebra_connected;
zclient->interface_add = rip_interface_add;
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c
index 084d58ee53..18a8d14f09 100644
--- a/ripngd/ripng_zebra.c
+++ b/ripngd/ripng_zebra.c
@@ -413,7 +413,7 @@ static void ripng_zebra_connected(struct zclient *zclient)
void zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
zclient->zebra_connected = ripng_zebra_connected;
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
new file mode 100644
index 0000000000..1c80cf055a
--- /dev/null
+++ b/sharpd/sharp_main.c
@@ -0,0 +1,162 @@
+/*
+ * SHARP - main code
+ * Copyright (C) Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include <lib/version.h>
+#include "getopt.h"
+#include "thread.h"
+#include "prefix.h"
+#include "linklist.h"
+#include "if.h"
+#include "vector.h"
+#include "vty.h"
+#include "command.h"
+#include "filter.h"
+#include "plist.h"
+#include "stream.h"
+#include "log.h"
+#include "memory.h"
+#include "privs.h"
+#include "sigevent.h"
+#include "zclient.h"
+#include "keychain.h"
+#include "distribute.h"
+#include "libfrr.h"
+#include "routemap.h"
+
+#include "sharp_zebra.h"
+#include "sharp_vty.h"
+
+uint32_t total_routes = 0;
+uint32_t installed_routes = 0;
+uint32_t removed_routes = 0;
+
+zebra_capabilities_t _caps_p[] = {
+ ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
+};
+
+struct zebra_privs_t sharp_privs = {
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
+#endif
+#if defined(VTY_GROUP)
+ .vty_group = VTY_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = array_size(_caps_p),
+ .cap_num_i = 0};
+
+struct option longopts[] = {{0}};
+
+/* Master of threads. */
+struct thread_master *master;
+
+/* SIGHUP handler. */
+static void sighup(void)
+{
+ zlog_info("SIGHUP received");
+}
+
+/* SIGINT / SIGTERM handler. */
+static void sigint(void)
+{
+ zlog_notice("Terminating on signal");
+
+ exit(0);
+}
+
+/* SIGUSR1 handler. */
+static void sigusr1(void)
+{
+ zlog_rotate();
+}
+
+struct quagga_signal_t sharp_signals[] = {
+ {
+ .signal = SIGHUP,
+ .handler = &sighup,
+ },
+ {
+ .signal = SIGUSR1,
+ .handler = &sigusr1,
+ },
+ {
+ .signal = SIGINT,
+ .handler = &sigint,
+ },
+ {
+ .signal = SIGTERM,
+ .handler = &sigint,
+ },
+};
+
+#define SHARP_VTY_PORT 2614
+
+FRR_DAEMON_INFO(sharpd, SHARP, .vty_port = SHARP_VTY_PORT,
+
+ .proghelp = "Implementation of a Sharp of routes daemon.",
+
+ .signals = sharp_signals,
+ .n_signals = array_size(sharp_signals),
+
+ .privs = &sharp_privs, )
+
+extern void sharp_vty_init(void);
+
+int main(int argc, char **argv, char **envp)
+{
+ frr_preinit(&sharpd_di, argc, argv);
+ frr_opt_add("", longopts, "");
+
+ while (1) {
+ int opt;
+
+ opt = frr_getopt(argc, argv, NULL);
+
+ if (opt == EOF)
+ break;
+
+ switch (opt) {
+ case 0:
+ break;
+ default:
+ frr_help_exit(1);
+ break;
+ }
+ }
+
+ master = frr_init();
+
+ vrf_init(NULL, NULL, NULL, NULL);
+
+ sharp_zebra_init();
+
+ /* Get configuration file. */
+ sharp_vty_init();
+
+ frr_config_fork();
+ frr_run(master);
+
+ /* Not reached. */
+ return 0;
+}
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
new file mode 100644
index 0000000000..47bb37ce92
--- /dev/null
+++ b/sharpd/sharp_vty.c
@@ -0,0 +1,114 @@
+/*
+ * SHARP - vty code
+ * Copyright (C) Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "vty.h"
+#include "command.h"
+#include "prefix.h"
+#include "nexthop.h"
+#include "log.h"
+
+#include "sharpd/sharp_zebra.h"
+#include "sharpd/sharp_vty.h"
+#include "sharpd/sharp_vty_clippy.c"
+
+extern uint32_t total_routes;
+extern uint32_t installed_routes;
+extern uint32_t removed_routes;
+
+DEFPY (install_routes,
+ install_routes_cmd,
+ "install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
+ "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")
+{
+ int i;
+ struct prefix p;
+ struct nexthop nhop;
+ uint32_t temp;
+
+ total_routes = routes;
+ installed_routes = 0;
+
+ memset(&p, 0, sizeof(p));
+ memset(&nhop, 0, sizeof(nhop));
+
+ p.family = AF_INET;
+ p.prefixlen = 32;
+ p.u.prefix4 = start;
+
+ nhop.gate.ipv4 = nexthop;
+ nhop.type = NEXTHOP_TYPE_IPV4;
+
+ zlog_debug("Inserting %ld routes", routes);
+
+ temp = ntohl(p.u.prefix4.s_addr);
+ for (i = 0 ; i < routes ; i++) {
+ route_add(&p, &nhop);
+ p.u.prefix4.s_addr = htonl(++temp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (remove_routes,
+ remove_routes_cmd,
+ "remove routes A.B.C.D$start (1-1000000)$routes",
+ "Remove some routes\n"
+ "Routes to remove\n"
+ "Starting spot\n"
+ "Routes to uniinstall\n")
+{
+ int i;
+ struct prefix p;
+ uint32_t temp;
+
+ total_routes = routes;
+ removed_routes = 0;
+
+ memset(&p, 0, sizeof(p));
+
+ p.family = AF_INET;
+ p.prefixlen = 32;
+ p.u.prefix4 = start;
+
+ zlog_debug("Removing %ld routes", routes);
+
+ temp = ntohl(p.u.prefix4.s_addr);
+ for (i = 0; i < routes ; i++) {
+ route_delete(&p);
+ p.u.prefix4.s_addr = htonl(++temp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+void sharp_vty_init(void)
+{
+ install_element(ENABLE_NODE, &install_routes_cmd);
+ install_element(ENABLE_NODE, &remove_routes_cmd);
+ return;
+}
diff --git a/sharpd/sharp_vty.h b/sharpd/sharp_vty.h
new file mode 100644
index 0000000000..d4af095e89
--- /dev/null
+++ b/sharpd/sharp_vty.h
@@ -0,0 +1,26 @@
+/*
+ * VTY library for SHARP
+ * Copyright (C) Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __SHARP_VTY_H__
+#define __SHARP_VTY_H__
+
+extern void sharp_vty_init(void);
+#endif
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
new file mode 100644
index 0000000000..4a5ae13c43
--- /dev/null
+++ b/sharpd/sharp_zebra.c
@@ -0,0 +1,208 @@
+/*
+ * Zebra connect code.
+ * Copyright (C) Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "thread.h"
+#include "command.h"
+#include "network.h"
+#include "prefix.h"
+#include "routemap.h"
+#include "table.h"
+#include "stream.h"
+#include "memory.h"
+#include "zclient.h"
+#include "filter.h"
+#include "plist.h"
+#include "log.h"
+#include "nexthop.h"
+
+#include "sharp_zebra.h"
+
+/* Zebra structure to hold current status. */
+struct zclient *zclient = NULL;
+
+/* For registering threads. */
+extern struct thread_master *master;
+
+static struct interface *zebra_interface_if_lookup(struct stream *s)
+{
+ char ifname_tmp[INTERFACE_NAMSIZ];
+
+ /* Read interface name. */
+ stream_get(ifname_tmp, s, INTERFACE_NAMSIZ);
+
+ /* And look it up. */
+ return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
+}
+
+/* Inteface addition message from zebra. */
+static int interface_add(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct interface *ifp;
+
+ ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
+
+ if (!ifp->info)
+ return 0;
+
+ return 0;
+}
+
+static int interface_delete(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct interface *ifp;
+ struct stream *s;
+
+ s = zclient->ibuf;
+ /* zebra_interface_state_read () updates interface structure in iflist
+ */
+ ifp = zebra_interface_state_read(s, vrf_id);
+
+ if (ifp == NULL)
+ return 0;
+
+ if_set_index(ifp, IFINDEX_INTERNAL);
+
+ return 0;
+}
+
+static int interface_address_add(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+
+ zebra_interface_address_read(command, zclient->ibuf, vrf_id);
+
+ return 0;
+}
+
+static int interface_address_delete(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct connected *c;
+
+ c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
+
+ if (!c)
+ return 0;
+
+ connected_free(c);
+ return 0;
+}
+
+static int interface_state_up(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+
+ zebra_interface_if_lookup(zclient->ibuf);
+
+ return 0;
+}
+
+static int interface_state_down(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+
+ zebra_interface_state_read(zclient->ibuf, vrf_id);
+
+ return 0;
+}
+
+extern uint32_t total_routes;
+extern uint32_t installed_routes;
+
+static int notify_owner(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct prefix p;
+ enum zapi_route_notify_owner note;
+
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &note))
+ return -1;
+
+ installed_routes++;
+
+ if (total_routes == installed_routes)
+ zlog_debug("Installed All Items");
+ return 0;
+}
+
+static void zebra_connected(struct zclient *zclient)
+{
+ zclient_send_reg_requests(zclient, VRF_DEFAULT);
+}
+
+void route_add(struct prefix *p, struct nexthop *nh)
+{
+ struct zapi_route api;
+ struct zapi_nexthop *api_nh;
+
+ memset(&api, 0, sizeof(api));
+ api.vrf_id = VRF_DEFAULT;
+ api.type = ZEBRA_ROUTE_SHARP;
+ api.safi = SAFI_UNICAST;
+ memcpy(&api.prefix, p, sizeof(*p));
+
+ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+ api_nh = &api.nexthops[0];
+ api_nh->gate.ipv4 = nh->gate.ipv4;
+ api_nh->type = nh->type;
+ api_nh->ifindex = nh->ifindex;
+ api.nexthop_num = 1;
+
+ zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
+}
+
+void route_delete(struct prefix *p)
+{
+ struct zapi_route api;
+
+ memset(&api, 0, sizeof(api));
+ api.vrf_id = VRF_DEFAULT;
+ api.type = ZEBRA_ROUTE_SHARP;
+ api.safi = SAFI_UNICAST;
+ memcpy(&api.prefix, p, sizeof(*p));
+ zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+ return;
+}
+
+extern struct zebra_privs_t sharp_privs;
+
+void sharp_zebra_init(void)
+{
+ struct zclient_options opt = { .receive_notify = true };
+
+ zclient = zclient_new_notify(master, &opt);
+
+ zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
+ zclient->zebra_connected = zebra_connected;
+ zclient->interface_add = interface_add;
+ zclient->interface_delete = interface_delete;
+ zclient->interface_up = interface_state_up;
+ zclient->interface_down = interface_state_down;
+ zclient->interface_address_add = interface_address_add;
+ zclient->interface_address_delete = interface_address_delete;
+ zclient->notify_owner = notify_owner;
+}
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
new file mode 100644
index 0000000000..97100f61a6
--- /dev/null
+++ b/sharpd/sharp_zebra.h
@@ -0,0 +1,29 @@
+/*
+ * Zebra connect library for SHARP
+ * Copyright (C) Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __SHARP_ZEBRA_H__
+#define __SHARP_ZEBRA_H__
+
+extern void sharp_zebra_init(void);
+
+extern void route_add(struct prefix *p, struct nexthop *nh);
+extern void route_delete(struct prefix *p);
+#endif
diff --git a/sharpd/sharpd.conf.sample b/sharpd/sharpd.conf.sample
new file mode 100644
index 0000000000..bb1c2edca8
--- /dev/null
+++ b/sharpd/sharpd.conf.sample
@@ -0,0 +1,3 @@
+!
+!
+log stdout
diff --git a/sharpd/subdir.am b/sharpd/subdir.am
new file mode 100644
index 0000000000..da7d68e0bc
--- /dev/null
+++ b/sharpd/subdir.am
@@ -0,0 +1,21 @@
+#
+# sharpd
+#
+
+if SHARPD
+noinst_LIBRARIES += sharpd/libsharp.a
+sbin_PROGRAMS += sharpd/sharpd
+dist_examples_DATA += sharpd/sharpd.conf.sample
+endif
+
+sharpd_libsharp_a_SOURCES = \
+ sharpd/sharp_zebra.c \
+ sharpd/sharp_vty.c \
+ # end
+
+sharpd/sharp_vty_clippy.c: $(CLIPPY_DEPS)
+sharpd/sharp_vty.$(OBJEXT): sharpd/sharp_vty_clippy.c
+
+sharpd_sharpd_SOURCES = sharpd/sharp_main.c
+sharpd_sharpd_LDADD = sharpd/libsharp.a lib/libfrr.la @LIBCAP@
+
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index ccd3b6f4c2..247fcf7da0 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -374,7 +374,7 @@ static int global_test_init(void)
{
qobj_init();
master = thread_master_create(NULL);
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
bgp_master_init(master);
vrf_init(NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c
index 5e604db61a..b08f63b70f 100644
--- a/tests/test_lblmgr.c
+++ b/tests/test_lblmgr.c
@@ -115,7 +115,7 @@ void init_zclient(struct thread_master *master, char *lm_zserv_path)
{
frr_zclient_addr(&zclient_addr, &zclient_addr_len, lm_zserv_path);
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
/* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */
zclient->sock = -1;
zclient->redist_default = ZEBRA_ROUTE_LDP;
diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons
index a460827924..ac17fed03a 100644
--- a/tools/etc/frr/daemons
+++ b/tools/etc/frr/daemons
@@ -33,3 +33,4 @@ ldpd=no
nhrpd=no
eigrpd=no
babeld=no
+sharpd=no
diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf
index 0d92d13671..3f40836c90 100644
--- a/tools/etc/frr/daemons.conf
+++ b/tools/etc/frr/daemons.conf
@@ -16,6 +16,7 @@ ldpd_options=" --daemon -A 127.0.0.1"
nhrpd_options=" --daemon -A 127.0.0.1"
eigrpd_options=" --daemon -A 127.0.0.1"
babeld_options=" --daemon -A 127.0.0.1"
+sharpd_options=" --daemon -A 127.0.0.1"
# The list of daemons to watch is automatically generated by the init script.
watchfrr_enable=yes
diff --git a/tools/etc/iproute2/rt_protos.d/frr.conf b/tools/etc/iproute2/rt_protos.d/frr.conf
index 2d3b884e7e..b8d4c1c03b 100644
--- a/tools/etc/iproute2/rt_protos.d/frr.conf
+++ b/tools/etc/iproute2/rt_protos.d/frr.conf
@@ -8,3 +8,4 @@
191 nhrp
192 eigrp
193 ldp
+194 sharp \ No newline at end of file
diff --git a/tools/frr b/tools/frr
index 78190aadb0..0f6140d3ec 100755
--- a/tools/frr
+++ b/tools/frr
@@ -21,7 +21,7 @@ V_PATH=/var/run/frr
# Local Daemon selection may be done by using /etc/frr/daemons.
# See /usr/share/doc/frr/README.Debian.gz for further information.
# Keep zebra first and do not list watchfrr!
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd"
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd"
MAX_INSTANCES=5
RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 5156d336b3..3ddb6aba54 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -132,6 +132,10 @@ vtysh_scan += $(top_srcdir)/babeld/babel_zebra.c
vtysh_scan += $(top_srcdir)/babeld/babeld.c
endif
+if SHARPD
+vtysh_scan += $(top_srcdir)/sharpd/sharp_vty.c
+endif
+
if SNMP
vtysh_scan += $(top_srcdir)/lib/agentx.c
endif
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index f33c7b9603..dedf3d1647 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -82,7 +82,7 @@ foreach (@ARGV) {
$protocol = "VTYSH_RIPD";
}
elsif ($file =~ /lib\/routemap\.c$/) {
- $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD";
+ $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_SHARPD";
}
elsif ($file =~ /lib\/vrf\.c$/) {
$protocol = "VTYSH_ALL";
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index b021607240..76343ded60 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -74,6 +74,7 @@ struct vtysh_client vtysh_client[] = {
{.fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .next = NULL},
{.fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL},
{.fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL},
+ {.fd = -1, .name = "sharpd", .flag = VTYSH_SHARPD, .next = NULL},
{.fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL},
};
@@ -1045,7 +1046,9 @@ struct cmd_node link_params_node = {
LINK_PARAMS_NODE, "%s(config-link-params)# ",
};
+#if defined(HAVE_RPKI)
static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
+#endif
/* Defined in lib/vty.c */
extern struct cmd_node vty_node;
@@ -1183,6 +1186,7 @@ DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
return CMD_SUCCESS;
}
+#if defined(HAVE_RPKI)
DEFUNSH(VTYSH_BGPD,
rpki,
rpki_cmd,
@@ -1211,6 +1215,7 @@ DEFUNSH(VTYSH_BGPD,
{
return rpki_exit(self, vty, argc, argv);
}
+#endif
DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
"address-family <l2vpn evpn>",
@@ -3010,7 +3015,9 @@ void vtysh_init_vty(void)
install_node(&keychain_key_node, NULL);
install_node(&isis_node, NULL);
install_node(&vty_node, NULL);
+#if defined(HAVE_RPKI)
install_node(&rpki_node, NULL);
+#endif
struct cmd_node *node;
for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
@@ -3209,10 +3216,12 @@ void vtysh_init_vty(void)
install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
install_element(BGP_IPV6L_NODE, &exit_address_family_cmd);
+#if defined(HAVE_RPKI)
install_element(CONFIG_NODE, &rpki_cmd);
install_element(RPKI_NODE, &rpki_exit_cmd);
install_element(RPKI_NODE, &rpki_quit_cmd);
install_element(RPKI_NODE, &vtysh_end_all_cmd);
+#endif
/* EVPN commands */
install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 9d6ea4bda4..c584d7a905 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -37,13 +37,15 @@ DECLARE_MGROUP(MVTYSH)
#define VTYSH_NHRPD 0x800
#define VTYSH_EIGRPD 0x1000
#define VTYSH_BABELD 0x2000
+#define VTYSH_SHARPD 0x4000
+
/* commands in REALLYALL are crucial to correct vtysh operation */
#define VTYSH_REALLYALL ~0U
/* watchfrr is not in ALL since library CLI functions should not be
* run on it (logging & co. should stay in a fixed/frozen config, and
* things like prefix lists are not even initialised) */
-#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD
+#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_PIMD|VTYSH_EIGRPD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD
#define VTYSH_NS VTYSH_ZEBRA
diff --git a/zebra/client_main.c b/zebra/client_main.c
index 95b9d00dc0..9b82e48261 100644
--- a/zebra/client_main.c
+++ b/zebra/client_main.c
@@ -184,7 +184,7 @@ int main(int argc, char **argv)
master = thread_master_create(NULL);
/* Establish connection to zebra. */
- zclient = zclient_new(master);
+ zclient = zclient_new_notify(master, &zclient_options_default);
zclient->enable = 1;
zclient_socket_connect(zclient);
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 6fbb751789..bf4522b70f 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -221,7 +221,7 @@ static void lm_zclient_init(char *lm_zserv_path)
lm_zserv_path);
/* Set default values. */
- zclient = zclient_new(zebrad.master);
+ zclient = zclient_new_notify(zebrad.master, &zclient_options_default);
zclient->sock = -1;
zclient->t_connect = NULL;
lm_zclient_connect(NULL);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index a1ef5ba986..3830e1fbde 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -98,7 +98,7 @@ static inline int is_selfroute(int proto)
|| (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
|| (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
|| (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
- || (proto == RTPROT_RIP)) {
+ || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)) {
return 1;
}
@@ -139,6 +139,9 @@ static inline int zebra2proto(int proto)
case ZEBRA_ROUTE_LDP:
proto = RTPROT_LDP;
break;
+ case ZEBRA_ROUTE_SHARP:
+ proto = RTPROT_SHARP;
+ break;
default:
proto = RTPROT_ZEBRA;
break;
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index afb03f878d..51350fd6fb 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -51,6 +51,7 @@
#define RTPROT_NHRP 191
#define RTPROT_EIGRP 192
#define RTPROT_LDP 193
+#define RTPROT_SHARP 194
void rt_netlink_init(void);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index e96a988edf..791f319120 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1028,6 +1028,14 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
}
}
+ /*
+ * If this is a replace to a new RE let the originator of the RE
+ * know that they've lost
+ */
+ if (old && old != re)
+ zsend_route_notify_owner(old->type, old->instance,
+ old->vrf_id, p,
+ ZAPI_ROUTE_BETTER_ADMIN_WON);
/*
* Make sure we update the FPM any time we send new information to
@@ -1048,7 +1056,11 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
else
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
- }
+ zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
+ p, ZAPI_ROUTE_INSTALLED);
+ } else
+ zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
+ p, ZAPI_ROUTE_FAIL_INSTALL);
return ret;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index f5caf9d0b9..9c70b55a1a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -759,7 +759,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni,
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
- client = zebra_find_client(ZEBRA_ROUTE_BGP);
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
if (!client)
return 0;
@@ -2122,7 +2122,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
struct zserv *client;
struct stream *s;
- client = zebra_find_client(ZEBRA_ROUTE_BGP);
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
if (!client)
return 0;
@@ -2154,7 +2154,7 @@ static int zvni_send_del_to_client(vni_t vni)
struct zserv *client;
struct stream *s;
- client = zebra_find_client(ZEBRA_ROUTE_BGP);
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
if (!client)
return 0;
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 2389944e84..b6d70084c0 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -988,6 +988,43 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
return zebra_server_send_message(client);
}
+int zsend_route_notify_owner(u_char proto, u_short instance,
+ vrf_id_t vrf_id, struct prefix *p,
+ enum zapi_route_notify_owner note)
+{
+ struct zserv *client;
+ struct stream *s;
+ uint8_t blen;
+
+ client = zebra_find_client(proto, instance);
+ if (!client || !client->notify_owner) {
+ if (IS_ZEBRA_DEBUG_PACKET) {
+ char buff[PREFIX_STRLEN];
+
+ zlog_debug("Not Notifying Owner: %u about prefix %s",
+ proto, prefix2str(p, buff, sizeof(buff)));
+ }
+ return 0;
+ }
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zserv_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id);
+
+ stream_put(s, &note, sizeof(note));
+
+ stream_putc(s, p->family);
+
+ blen = prefix_blen(p);
+ stream_putc(s, p->prefixlen);
+ stream_put(s, &p->u.prefix, blen);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client);
+}
+
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
int zsend_router_id_update(struct zserv *client, struct prefix *p,
vrf_id_t vrf_id)
@@ -1884,9 +1921,13 @@ static void zread_hello(struct zserv *client)
/* type of protocol (lib/zebra.h) */
u_char proto;
u_short instance;
+ u_char notify;
STREAM_GETC(client->ibuf, proto);
STREAM_GETW(client->ibuf, instance);
+ STREAM_GETC(client->ibuf, notify);
+ if (notify)
+ client->notify_owner = true;
/* accept only dynamic routing protocols */
if ((proto < ZEBRA_ROUTE_MAX) && (proto > ZEBRA_ROUTE_STATIC)) {
@@ -2962,13 +3003,14 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
client->v6_route_del_cnt);
}
-struct zserv *zebra_find_client(u_char proto)
+struct zserv *zebra_find_client(u_char proto, u_short instance)
{
struct listnode *node, *nnode;
struct zserv *client;
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
- if (client->proto == proto)
+ if (client->proto == proto &&
+ client->instance == instance)
return client;
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 60e055088a..6077dc105a 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -75,6 +75,8 @@ struct zserv {
/* Router-id information. */
vrf_bitmap_t ridinfo;
+ bool notify_owner;
+
/* client's protocol */
u_char proto;
u_short instance;
@@ -183,6 +185,10 @@ extern int zsend_interface_vrf_update(struct zserv *, struct interface *,
extern int zsend_interface_link_params(struct zserv *, struct interface *);
extern int zsend_pw_update(struct zserv *, struct zebra_pw *);
+extern int zsend_route_notify_owner(u_char proto, u_short instance,
+ vrf_id_t vrf_id, struct prefix *p,
+ enum zapi_route_notify_owner note);
+
extern pid_t pid;
extern void zserv_create_header(struct stream *s, uint16_t cmd,
@@ -191,7 +197,7 @@ extern void zserv_nexthop_num_warn(const char *, const struct prefix *,
const unsigned int);
extern int zebra_server_send_message(struct zserv *client);
-extern struct zserv *zebra_find_client(u_char proto);
+extern struct zserv *zebra_find_client(u_char proto, u_short instance);
#if defined(HANDLE_ZAPI_FUZZING)
extern void zserv_read_file(char *input);