summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/user/setup.rst21
-rw-r--r--doc/user/zebra.rst87
-rw-r--r--staticd/static_nb.c17
-rw-r--r--staticd/static_nb_config.c8
-rw-r--r--staticd/static_routes.c7
-rw-r--r--staticd/static_routes.h13
-rw-r--r--staticd/static_vrf.c24
-rw-r--r--staticd/static_vty.c397
-rw-r--r--staticd/static_vty.h13
-rwxr-xr-xvtysh/extract.pl.in6
10 files changed, 425 insertions, 168 deletions
diff --git a/doc/user/setup.rst b/doc/user/setup.rst
index 64a33765c2..dbbfca21e7 100644
--- a/doc/user/setup.rst
+++ b/doc/user/setup.rst
@@ -176,6 +176,27 @@ Operations
This section covers a few common operational tasks and how to perform them.
+Interactive Shell
+^^^^^^^^^^^^^^^^^
+FRR offers an IOS-like interactive shell called ``vtysh`` where a user can run
+individual configuration or show commands. To get into this shell, issue the
+``vtysh`` command from either a privilege user (root, or with sudo) or a user
+account that is part of the ``frrvty`` group.
+e.g.
+
+.. code-block:: console
+
+ root@ub18:~# vtysh
+
+ Hello, this is FRRouting (version 8.1-dev).
+ Copyright 1996-2005 Kunihiro Ishiguro, et al.
+
+ ub18#
+
+.. note::
+ The default install location for vtysh is /usr/bin/vtysh
+
+
Restarting
^^^^^^^^^^
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 79036320b8..2d1dafd7b4 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -1241,36 +1241,103 @@ For protocols requiring an IPv6 router-id, the following commands are available:
.. _zebra-sysctl:
-Expected sysctl settings
-========================
+sysctl settings
+===============
The linux kernel has a variety of sysctl's that affect it's operation as a router. This
section is meant to act as a starting point for those sysctl's that must be used in
order to provide FRR with smooth operation as a router. This section is not meant
as the full documentation for sysctl's. The operator must use the sysctl documentation
-with the linux kernel for that.
+with the linux kernel for that. The following link has helpful references to many relevant
+sysctl values: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
+
+Expected sysctl settings
+^^^^^^^^^^^^^^^^^^^^^^^^
.. option:: net.ipv4.ip_forward = 1
- This option allows the linux kernel to forward ipv4 packets incoming from one interface
- to an outgoing interface. Without this no forwarding will take place from off box packets.
+ This global option allows the linux kernel to forward (route) ipv4 packets incoming from one
+ interface to an outgoing interface. If this is set to 0, the system will not route transit
+ ipv4 packets, i.e. packets that are not sent to/from a process running on the local system.
-.. option:: net.ipv6.conf.all_forwarding=1
+.. option:: net.ipv4.conf.{all,default,<interface>}.forwarding = 1
- This option allows the linux kernel to forward ipv6 packets incoming from one interface
- to an outgoing interface. Without this no forwarding will take place from off box packets.
+ The linux kernel can selectively enable forwarding (routing) of ipv4 packets on a per
+ interface basis. The forwarding check in the kernel dataplane occurs against the ingress
+ Layer 3 interface, i.e. if the ingress L3 interface has forwarding set to 0, packets will not
+ be routed.
-.. option:: net.ipv6.conf.all.keep_addr_on_down=1
+.. option:: net.ipv6.conf.{all,default,<interface>}.forwarding = 1
+
+ This per interface option allows the linux kernel to forward (route) transit ipv6 packets
+ i.e. incoming from one Layer 3 interface to an outgoing Layer 3 interface.
+ The forwarding check in the kernel dataplane occurs against the ingress Layer 3 interface,
+ i.e. if the ingress L3 interface has forwarding set to 0, packets will not be routed.
+
+.. option:: net.ipv6.conf.all.keep_addr_on_down = 1
When an interface is taken down, do not remove the v6 addresses associated with the interface.
This option is recommended because this is the default behavior for v4 as well.
-.. option:: net.ipv6.route.skip_notify_on_dev_down=1
+.. option:: net.ipv6.route.skip_notify_on_dev_down = 1
When an interface is taken down, the linux kernel will not notify, via netlink, about routes
that used that interface being removed from the FIB. This option is recommended because this
is the default behavior for v4 as well.
+Optional sysctl settings
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. option:: net.ipv4.conf.{all,default,<interface>}.bc_forwarding = 0
+
+ This per interface option allows the linux kernel to optionally allow Directed Broadcast
+ (i.e. Routed Broadcast or Subnet Broadcast) packets to be routed onto the connected network
+ segment where the subnet exists.
+ If the local router receives a routed packet destined for a broadcast address of a connected
+ subnet, setting bc_forwarding to 1 on the interface with the target subnet assigned to it will
+ allow non locally-generated packets to be routed via the broadcast route.
+ If bc_forwarding is set to 0, routed packets destined for a broadcast route will be dropped.
+ e.g.
+ Host1 (SIP:192.0.2.10, DIP:10.0.0.255) -> (eth0:192.0.2.1/24) Router1 (eth1:10.0.0.1/24) -> BC
+ If net.ipv4.conf.{all,default,<interface>}.bc_forwarding=1, then Router1 will forward each
+ packet destined to 10.0.0.255 onto the eth1 interface with a broadcast DMAC (ff:ff:ff:ff:ff:ff).
+
+.. option:: net.ipv4.conf.{all,default,<interface>}.arp_accept = 1
+
+ This per interface option allows the linux kernel to optionally skip the creation of ARP
+ entries upon the receipt of a Gratuitous ARP (GARP) frame carrying an IP that is not already
+ present in the ARP cache. Setting arp_accept to 0 on an interface will ensure NEW ARP entries
+ are not created due to the arrival of a GARP frame.
+ Note: This does not impact how the kernel reacts to GARP frames that carry a "known" IP
+ (that is already in the ARP cache) -- an existing ARP entry will always be updated
+ when a GARP for that IP is received.
+
+.. option:: net.ipv4.conf.{all,default,<interface>}.arp_ignore = 0
+
+ This per interface option allows the linux kernel to control what conditions must be met in
+ order for an ARP reply to be sent in response to an ARP request targeting a local IP address.
+ When arp_ignore is set to 0, the kernel will send ARP replies in response to any ARP Request
+ with a Target-IP matching a local address.
+ When arp_ignore is set to 1, the kernel will send ARP replies if the Target-IP in the ARP
+ Request matches an IP address on the interface the Request arrived at.
+ When arp_ignore is set to 2, the kernel will send ARP replies only if the Target-IP matches an
+ IP address on the interface where the Request arrived AND the Sender-IP falls within the subnet
+ assigned to the local IP/interface.
+
+.. option:: net.ipv4.conf.{all,default,<interface>}.arp_notify = 1
+
+ This per interface option allows the linux kernel to decide whether to send a Gratuitious ARP
+ (GARP) frame when the Layer 3 interface comes UP.
+ When arp_notify is set to 0, no GARP is sent.
+ When arp_notify is set to 1, a GARP is sent when the interface comes UP.
+
+.. option:: net.ipv6.conf.{all,default,<interface>}.ndisc_notify = 1
+
+ This per interface option allows the linux kernel to decide whether to send an Unsolicited
+ Neighbor Advertisement (U-NA) frame when the Layer 3 interface comes UP.
+ When ndisc_notify is set to 0, no U-NA is sent.
+ When ndisc_notify is set to 1, a U-NA is sent when the interface comes UP.
+
Debugging
=========
diff --git a/staticd/static_nb.c b/staticd/static_nb.c
index c1a6253a1d..5935364d5a 100644
--- a/staticd/static_nb.c
+++ b/staticd/static_nb.c
@@ -21,7 +21,7 @@
#include "northbound.h"
#include "libfrr.h"
#include "static_nb.h"
-
+#include "static_vty.h"
/* clang-format off */
@@ -29,10 +29,18 @@ const struct frr_yang_module_info frr_staticd_info = {
.name = "frr-staticd",
.nodes = {
{
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd",
+ .cbs = {
+ .cli_show = static_cli_show,
+ .cli_show_end = static_cli_show_end,
+ }
+ },
+ {
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list",
.cbs = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_destroy,
+ .cli_cmp = static_route_list_cli_cmp,
}
},
{
@@ -40,6 +48,7 @@ const struct frr_yang_module_info frr_staticd_info = {
.cbs = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_destroy,
+ .cli_cmp = static_path_list_cli_cmp,
}
},
{
@@ -55,6 +64,8 @@ const struct frr_yang_module_info frr_staticd_info = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_destroy,
.pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
+ .cli_show = static_nexthop_cli_show,
+ .cli_cmp = static_nexthop_cli_cmp,
}
},
{
@@ -110,6 +121,7 @@ const struct frr_yang_module_info frr_staticd_info = {
.cbs = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy,
+ .cli_cmp = static_src_list_cli_cmp,
}
},
{
@@ -117,6 +129,7 @@ const struct frr_yang_module_info frr_staticd_info = {
.cbs = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_destroy,
+ .cli_cmp = static_path_list_cli_cmp,
}
},
{
@@ -132,6 +145,8 @@ const struct frr_yang_module_info frr_staticd_info = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_create,
.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_destroy,
.pre_validate = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_pre_validate,
+ .cli_show = static_src_nexthop_cli_show,
+ .cli_cmp = static_nexthop_cli_cmp,
}
},
{
diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c
index deeca97b0e..470c7bdad5 100644
--- a/staticd/static_nb_config.c
+++ b/staticd/static_nb_config.c
@@ -122,7 +122,7 @@ struct nexthop_iter {
static int nexthop_iter_cb(const struct lyd_node *dnode, void *arg)
{
struct nexthop_iter *iter = arg;
- int nh_type;
+ enum static_nh_type nh_type;
nh_type = yang_dnode_get_enum(dnode, "./nh-type");
@@ -141,7 +141,7 @@ static bool static_nexthop_create(struct nb_cb_create_args *args)
struct static_path *pn;
struct ipaddr ipaddr;
struct static_nexthop *nh;
- int nh_type;
+ enum static_nh_type nh_type;
const char *ifname;
const char *nh_vrf;
@@ -304,7 +304,7 @@ static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args)
static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
{
struct static_nexthop *nh;
- static_types nh_type;
+ enum static_nh_type nh_type;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -352,7 +352,7 @@ static int static_nexthop_color_destroy(struct nb_cb_destroy_args *args)
static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args)
{
struct static_nexthop *nh;
- static_types nh_type;
+ enum static_nh_type nh_type;
switch (args->event) {
case NB_EV_VALIDATE:
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index 77a10092f8..60f384e517 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -186,7 +186,8 @@ void static_del_route(struct route_node *rn)
route_unlock_node(rn);
}
-bool static_add_nexthop_validate(const char *nh_vrf_name, static_types type,
+bool static_add_nexthop_validate(const char *nh_vrf_name,
+ enum static_nh_type type,
struct ipaddr *ipaddr)
{
struct vrf *vrf;
@@ -257,7 +258,7 @@ void static_del_path(struct static_path *pn)
}
struct static_nexthop *static_add_nexthop(struct static_path *pn,
- static_types type,
+ enum static_nh_type type,
struct ipaddr *ipaddr,
const char *ifname,
const char *nh_vrf, uint32_t color)
@@ -772,7 +773,7 @@ void static_ifindex_update(struct interface *ifp, bool up)
static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
}
-void static_get_nh_type(static_types stype, char *type, size_t size)
+void static_get_nh_type(enum static_nh_type stype, char *type, size_t size)
{
switch (stype) {
case STATIC_IFNAME:
diff --git a/staticd/static_routes.h b/staticd/static_routes.h
index 2211384916..c901a8926a 100644
--- a/staticd/static_routes.h
+++ b/staticd/static_routes.h
@@ -47,14 +47,14 @@ enum static_blackhole_type {
* The order for below macros should be in sync with
* yang model typedef nexthop-type
*/
-typedef enum {
+enum static_nh_type {
STATIC_IFNAME = 1,
STATIC_IPV4_GATEWAY,
STATIC_IPV4_GATEWAY_IFNAME,
STATIC_IPV6_GATEWAY,
STATIC_IPV6_GATEWAY_IFNAME,
STATIC_BLACKHOLE,
-} static_types;
+};
/*
* Route Creation gives us:
@@ -123,7 +123,7 @@ struct static_nexthop {
enum static_install_states state;
/* Flag for this static route's type. */
- static_types type;
+ enum static_nh_type type;
/*
* Nexthop value.
@@ -169,7 +169,7 @@ extern struct zebra_privs_t static_privs;
void static_fixup_vrf_ids(struct static_vrf *svrf);
extern struct static_nexthop *
-static_add_nexthop(struct static_path *pn, static_types type,
+static_add_nexthop(struct static_path *pn, enum static_nh_type type,
struct ipaddr *ipaddr, const char *ifname,
const char *nh_vrf, uint32_t color);
extern void static_install_nexthop(struct static_nexthop *nh);
@@ -194,9 +194,10 @@ extern struct static_path *static_add_path(struct route_node *rn,
uint32_t table_id, uint8_t distance);
extern void static_del_path(struct static_path *pn);
-extern void static_get_nh_type(static_types stype, char *type, size_t size);
+extern void static_get_nh_type(enum static_nh_type stype, char *type,
+ size_t size);
extern bool static_add_nexthop_validate(const char *nh_vrf_name,
- static_types type,
+ enum static_nh_type type,
struct ipaddr *ipaddr);
extern struct stable_info *static_get_stable_info(struct route_node *rn);
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 740d904690..4bea3075c9 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -23,11 +23,11 @@
#include "nexthop.h"
#include "table.h"
#include "srcdest_table.h"
+#include "northbound_cli.h"
#include "static_vrf.h"
#include "static_routes.h"
#include "static_zebra.h"
-#include "static_vty.h"
DEFINE_MTYPE_STATIC(STATIC, STATIC_RTABLE_INFO, "Static Route Table Info");
@@ -150,24 +150,16 @@ struct static_vrf *static_vrf_lookup_by_name(const char *name)
static int static_vrf_config_write(struct vty *vty)
{
- struct vrf *vrf;
-
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- if (vrf->vrf_id != VRF_DEFAULT)
- vty_frame(vty, "vrf %s\n", vrf->name);
+ struct lyd_node *dnode;
+ int written = 0;
- static_config(vty, vrf->info, AFI_IP,
- SAFI_UNICAST, "ip route");
- static_config(vty, vrf->info, AFI_IP,
- SAFI_MULTICAST, "ip mroute");
- static_config(vty, vrf->info, AFI_IP6,
- SAFI_UNICAST, "ipv6 route");
-
- if (vrf->vrf_id != VRF_DEFAULT)
- vty_endframe(vty, "exit-vrf\n!\n");
+ dnode = yang_dnode_get(running_config->dnode, "/frr-routing:routing");
+ if (dnode) {
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ written = 1;
}
- return 0;
+ return written;
}
void static_vrf_init(void)
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index f16b40a23f..751a262775 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -56,7 +56,7 @@ static int static_route_leak(struct vty *vty, const char *svrf,
int ret;
struct prefix p, src;
struct in_addr mask;
- uint8_t type;
+ enum static_nh_type type;
const char *bh_type;
char xpath_prefix[XPATH_MAXLEN];
char xpath_nexthop[XPATH_MAXLEN];
@@ -357,129 +357,6 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi,
table_str, false, NULL);
}
-/* Write static route configuration. */
-int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi,
- safi_t safi, const char *cmd)
-{
- char spacing[100];
- struct route_node *rn;
- struct static_nexthop *nh;
- struct static_path *pn;
- struct route_table *stable;
- struct static_route_info *si;
- char buf[SRCDEST2STR_BUFFER];
- int write = 0;
- struct stable_info *info;
-
- stable = svrf->stable[afi][safi];
- if (stable == NULL)
- return write;
-
- snprintf(spacing, sizeof(spacing), "%s%s",
- (svrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ", cmd);
-
- for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
- si = static_route_info_from_rnode(rn);
- if (!si)
- continue;
- info = static_get_stable_info(rn);
- frr_each(static_path_list, &si->path_list, pn) {
- frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
- vty_out(vty, "%s %s", spacing,
- srcdest_rnode2str(rn, buf,
- sizeof(buf)));
-
- switch (nh->type) {
- case STATIC_IPV4_GATEWAY:
- vty_out(vty, " %pI4", &nh->addr.ipv4);
- break;
- case STATIC_IPV6_GATEWAY:
- vty_out(vty, " %s",
- inet_ntop(AF_INET6,
- &nh->addr.ipv6, buf,
- sizeof(buf)));
- break;
- case STATIC_IFNAME:
- vty_out(vty, " %s", nh->ifname);
- break;
- case STATIC_BLACKHOLE:
- switch (nh->bh_type) {
- case STATIC_BLACKHOLE_DROP:
- vty_out(vty, " blackhole");
- break;
- case STATIC_BLACKHOLE_NULL:
- vty_out(vty, " Null0");
- break;
- case STATIC_BLACKHOLE_REJECT:
- vty_out(vty, " reject");
- break;
- }
- break;
- case STATIC_IPV4_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET,
- &nh->addr.ipv4, buf,
- sizeof(buf)),
- nh->ifname);
- break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET6,
- &nh->addr.ipv6, buf,
- sizeof(buf)),
- nh->ifname);
- break;
- }
-
- if (pn->tag)
- vty_out(vty, " tag %" ROUTE_TAG_PRI,
- pn->tag);
-
- if (pn->distance
- != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out(vty, " %u", pn->distance);
-
- /* Label information */
- if (nh->snh_label.num_labels)
- vty_out(vty, " label %s",
- mpls_label2str(
- nh->snh_label
- .num_labels,
- nh->snh_label.label,
- buf, sizeof(buf), 0));
-
- if (!strmatch(nh->nh_vrfname,
- info->svrf->vrf->name))
- vty_out(vty, " nexthop-vrf %s",
- nh->nh_vrfname);
-
- /*
- * table ID from VRF overrides
- * configured
- */
- if (pn->table_id
- && svrf->vrf->data.l.table_id
- == RT_TABLE_MAIN)
- vty_out(vty, " table %u", pn->table_id);
-
- if (nh->onlink)
- vty_out(vty, " onlink");
-
- /*
- * SR-TE color
- */
- if (nh->color != 0)
- vty_out(vty, " color %u", nh->color);
-
- vty_out(vty, "\n");
-
- write = 1;
- }
- }
- }
- return write;
-}
-
/* Static unicast routes for multicast RPF lookup. */
DEFPY_YANG (ip_mroute_dist,
ip_mroute_dist_cmd,
@@ -1124,6 +1001,278 @@ DEFPY_YANG(ipv6_route_vrf,
ifname, flag, tag_str, distance_str, label,
table_str, false, color_str);
}
+
+void static_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "../vrf");
+ if (strcmp(vrf, VRF_DEFAULT_NAME))
+ vty_out(vty, "vrf %s\n", vrf);
+}
+
+void static_cli_show_end(struct vty *vty, struct lyd_node *dnode)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "../vrf");
+ if (strcmp(vrf, VRF_DEFAULT_NAME))
+ vty_out(vty, "exit-vrf\n");
+}
+
+struct mpls_label_iter {
+ struct vty *vty;
+ bool first;
+};
+
+static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct mpls_label_iter *iter = arg;
+
+ if (yang_dnode_exists(dnode, "./label")) {
+ if (iter->first)
+ vty_out(iter->vty, " label %s",
+ yang_dnode_get_string(dnode, "./label"));
+ else
+ vty_out(iter->vty, "/%s",
+ yang_dnode_get_string(dnode, "./label"));
+ iter->first = false;
+ }
+
+ return YANG_ITER_CONTINUE;
+}
+
+static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
+ const struct lyd_node *src,
+ const struct lyd_node *path,
+ const struct lyd_node *nexthop, bool show_defaults)
+{
+ const char *vrf;
+ const char *afi_safi;
+ afi_t afi;
+ safi_t safi;
+ enum static_nh_type nh_type;
+ enum static_blackhole_type bh_type;
+ uint32_t tag;
+ uint8_t distance;
+ struct mpls_label_iter iter;
+ const char *nexthop_vrf;
+ uint32_t table_id;
+ bool onlink;
+
+ vrf = yang_dnode_get_string(route, "../../vrf");
+
+ afi_safi = yang_dnode_get_string(route, "./afi-safi");
+ yang_afi_safi_identity2value(afi_safi, &afi, &safi);
+
+ if (afi == AFI_IP)
+ vty_out(vty, "%sip",
+ strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
+ else
+ vty_out(vty, "%sipv6",
+ strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
+
+ if (safi == SAFI_UNICAST)
+ vty_out(vty, " route");
+ else
+ vty_out(vty, " mroute");
+
+ vty_out(vty, " %s", yang_dnode_get_string(route, "./prefix"));
+
+ if (src)
+ vty_out(vty, " from %s",
+ yang_dnode_get_string(src, "./src-prefix"));
+
+ nh_type = yang_dnode_get_enum(nexthop, "./nh-type");
+ switch (nh_type) {
+ case STATIC_IFNAME:
+ vty_out(vty, " %s",
+ yang_dnode_get_string(nexthop, "./interface"));
+ break;
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV6_GATEWAY:
+ vty_out(vty, " %s",
+ yang_dnode_get_string(nexthop, "./gateway"));
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ vty_out(vty, " %s",
+ yang_dnode_get_string(nexthop, "./gateway"));
+ vty_out(vty, " %s",
+ yang_dnode_get_string(nexthop, "./interface"));
+ break;
+ case STATIC_BLACKHOLE:
+ bh_type = yang_dnode_get_enum(nexthop, "./bh-type");
+ switch (bh_type) {
+ case STATIC_BLACKHOLE_DROP:
+ vty_out(vty, " blackhole");
+ break;
+ case STATIC_BLACKHOLE_NULL:
+ vty_out(vty, " Null0");
+ break;
+ case STATIC_BLACKHOLE_REJECT:
+ vty_out(vty, " reject");
+ break;
+ }
+ break;
+ }
+
+ if (yang_dnode_exists(path, "./tag")) {
+ tag = yang_dnode_get_uint32(path, "./tag");
+ if (tag != 0 || show_defaults)
+ vty_out(vty, " tag %" PRIu32, tag);
+ }
+
+ distance = yang_dnode_get_uint8(path, "./distance");
+ if (distance != ZEBRA_STATIC_DISTANCE_DEFAULT || show_defaults)
+ vty_out(vty, " %" PRIu8, distance);
+
+ iter.vty = vty;
+ iter.first = true;
+ yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop,
+ "./mpls-label-stack/entry");
+
+ nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf");
+ if (strcmp(vrf, nexthop_vrf))
+ vty_out(vty, " nexthop-vrf %s", nexthop_vrf);
+
+ table_id = yang_dnode_get_uint32(path, "./table-id");
+ if (table_id || show_defaults)
+ vty_out(vty, " table %" PRIu32, table_id);
+
+ if (yang_dnode_exists(nexthop, "./onlink")) {
+ onlink = yang_dnode_get_bool(nexthop, "./onlink");
+ if (onlink)
+ vty_out(vty, " onlink");
+ }
+
+ if (yang_dnode_exists(nexthop, "./srte-color"))
+ vty_out(vty, " color %s",
+ yang_dnode_get_string(nexthop, "./srte-color"));
+
+ vty_out(vty, "\n");
+}
+
+void static_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
+ const struct lyd_node *route =
+ yang_dnode_get_parent(path, "route-list");
+
+ nexthop_cli_show(vty, route, NULL, path, dnode, show_defaults);
+}
+
+void static_src_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
+ const struct lyd_node *src = yang_dnode_get_parent(path, "src-list");
+ const struct lyd_node *route = yang_dnode_get_parent(src, "route-list");
+
+ nexthop_cli_show(vty, route, src, path, dnode, show_defaults);
+}
+
+int static_nexthop_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+{
+ enum static_nh_type nh_type1, nh_type2;
+ struct prefix prefix1, prefix2;
+ int ret = 0;
+
+ nh_type1 = yang_dnode_get_enum(dnode1, "./nh-type");
+ nh_type2 = yang_dnode_get_enum(dnode2, "./nh-type");
+
+ if (nh_type1 != nh_type2)
+ return (int)nh_type1 - (int)nh_type2;
+
+ switch (nh_type1) {
+ case STATIC_IFNAME:
+ ret = if_cmp_name_func(
+ yang_dnode_get_string(dnode1, "./interface"),
+ yang_dnode_get_string(dnode2, "./interface"));
+ break;
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV6_GATEWAY:
+ yang_dnode_get_prefix(&prefix1, dnode1, "./gateway");
+ yang_dnode_get_prefix(&prefix2, dnode2, "./gateway");
+ ret = prefix_cmp(&prefix1, &prefix2);
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ yang_dnode_get_prefix(&prefix1, dnode1, "./gateway");
+ yang_dnode_get_prefix(&prefix2, dnode2, "./gateway");
+ ret = prefix_cmp(&prefix1, &prefix2);
+ if (!ret)
+ ret = if_cmp_name_func(
+ yang_dnode_get_string(dnode1, "./interface"),
+ yang_dnode_get_string(dnode2, "./interface"));
+ break;
+ case STATIC_BLACKHOLE:
+ /* There's only one blackhole nexthop per route */
+ ret = 0;
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ return if_cmp_name_func(yang_dnode_get_string(dnode1, "./vrf"),
+ yang_dnode_get_string(dnode2, "./vrf"));
+}
+
+int static_route_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+{
+ const char *afi_safi1, *afi_safi2;
+ afi_t afi1, afi2;
+ safi_t safi1, safi2;
+ struct prefix prefix1, prefix2;
+
+ afi_safi1 = yang_dnode_get_string(dnode1, "./afi-safi");
+ yang_afi_safi_identity2value(afi_safi1, &afi1, &safi1);
+
+ afi_safi2 = yang_dnode_get_string(dnode2, "./afi-safi");
+ yang_afi_safi_identity2value(afi_safi2, &afi2, &safi2);
+
+ if (afi1 != afi2)
+ return (int)afi1 - (int)afi2;
+
+ if (safi1 != safi2)
+ return (int)safi1 - (int)safi2;
+
+ yang_dnode_get_prefix(&prefix1, dnode1, "./prefix");
+ yang_dnode_get_prefix(&prefix2, dnode2, "./prefix");
+
+ return prefix_cmp(&prefix1, &prefix2);
+}
+
+int static_src_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+{
+ struct prefix prefix1, prefix2;
+
+ yang_dnode_get_prefix(&prefix1, dnode1, "./src-prefix");
+ yang_dnode_get_prefix(&prefix2, dnode2, "./src-prefix");
+
+ return prefix_cmp(&prefix1, &prefix2);
+}
+
+int static_path_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2)
+{
+ uint32_t table_id1, table_id2;
+ uint8_t distance1, distance2;
+
+ table_id1 = yang_dnode_get_uint32(dnode1, "./table-id");
+ table_id2 = yang_dnode_get_uint32(dnode2, "./table-id");
+
+ if (table_id1 != table_id2)
+ return (int)table_id1 - (int)table_id2;
+
+ distance1 = yang_dnode_get_uint8(dnode1, "./distance");
+ distance2 = yang_dnode_get_uint8(dnode2, "./distance");
+
+ return (int)distance1 - (int)distance2;
+}
+
DEFPY_YANG(debug_staticd, debug_staticd_cmd,
"[no] debug static [{events$events|route$route}]",
NO_STR DEBUG_STR STATICD_STR
diff --git a/staticd/static_vty.h b/staticd/static_vty.h
index 01577685e5..8861afa468 100644
--- a/staticd/static_vty.h
+++ b/staticd/static_vty.h
@@ -23,8 +23,17 @@
extern "C" {
#endif
-int static_config(struct vty *vty, struct static_vrf *svrf,
- afi_t afi, safi_t safi, const char *cmd);
+void static_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void static_cli_show_end(struct vty *vty, struct lyd_node *dnode);
+void static_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+void static_src_nexthop_cli_show(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
+int static_nexthop_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
+int static_route_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
+int static_src_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
+int static_path_list_cli_cmp(struct lyd_node *dnode1, struct lyd_node *dnode2);
void static_vty_init(void);
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index 86cf8c9657..334bd7affa 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -42,11 +42,13 @@ sub scan_file {
$cppadd = $fabricd ? "-DFABRICD=1" : "";
- open (FH, "@CPP@ -P -std=gnu11 -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ @LIBYANG_CFLAGS@ $cppadd $file |");
+ $command_line = "@CPP@ -P -std=gnu11 -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ @LIBYANG_CFLAGS@ $cppadd $file |";
+ open (FH, $command_line)
+ || die "Open to the pipeline failed: $!\n\nCommand Issued:\n$command_line";
local $/; undef $/;
$line = <FH>;
if (!close (FH)) {
- printf "File: $file failed to compile, when extracting cli from it please inspect\n"
+ die "File: $file failed to compile:\n$!\nwhen extracting cli from it please inspect\n"
}
# ?: makes a group non-capturing