summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c7
-rw-r--r--bgpd/bgp_attr.c17
-rw-r--r--bgpd/bgp_errors.c2
-rw-r--r--bgpd/bgp_mplsvpn.c2
-rw-r--r--bgpd/bgp_route.c17
-rw-r--r--bgpd/bgp_vty.c54
-rw-r--r--bgpd/bgpd.c7
-rw-r--r--bgpd/bgpd.h83
-rw-r--r--configure.ac1
-rw-r--r--doc/developer/workflow.rst10
-rw-r--r--doc/manpages/vtysh.rst2
-rw-r--r--doc/user/ospf6d.rst252
-rw-r--r--doc/user/ospfd.rst33
-rw-r--r--doc/user/pim.rst4
-rw-r--r--lib/keychain.c155
-rw-r--r--lib/keychain.h45
-rw-r--r--lib/thread.c29
-rw-r--r--lib/thread.h1
-rw-r--r--ospf6d/ospf6_asbr.c8
-rw-r--r--ospf6d/ospf6_auth_trailer.c1000
-rw-r--r--ospf6d/ospf6_auth_trailer.h93
-rw-r--r--ospf6d/ospf6_interface.c243
-rw-r--r--ospf6d/ospf6_interface.h24
-rw-r--r--ospf6d/ospf6_intra.c2
-rw-r--r--ospf6d/ospf6_main.c2
-rw-r--r--ospf6d/ospf6_message.c238
-rw-r--r--ospf6d/ospf6_message.h14
-rw-r--r--ospf6d/ospf6_neighbor.c67
-rw-r--r--ospf6d/ospf6_neighbor.h8
-rw-r--r--ospf6d/ospf6_network.c16
-rw-r--r--ospf6d/ospf6_proto.c8
-rw-r--r--ospf6d/ospf6_proto.h15
-rw-r--r--ospf6d/ospf6_route.c6
-rw-r--r--ospf6d/ospf6_top.c22
-rw-r--r--ospf6d/ospf6_top.h2
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospf6d/ospf6d.c5
-rw-r--r--ospf6d/subdir.am3
-rw-r--r--ospfd/ospf_asbr.c8
-rw-r--r--ospfd/ospf_gr_helper.c4
-rw-r--r--ospfd/ospf_vty.c4
-rw-r--r--ospfd/ospf_zebra.c2
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--pathd/path_errors.c2
-rw-r--r--pathd/path_pcep_config.c2
-rw-r--r--pathd/pathd.c6
-rw-r--r--pceplib/pcep_timers.c2
-rw-r--r--pimd/pim_assert.c99
-rw-r--r--pimd/pim_assert.h4
-rw-r--r--pimd/pim_bfd.c4
-rw-r--r--pimd/pim_bsm.c25
-rw-r--r--pimd/pim_cmd.c99
-rw-r--r--pimd/pim_hello.c168
-rw-r--r--pimd/pim_hello.h4
-rw-r--r--pimd/pim_iface.c111
-rw-r--r--pimd/pim_iface.h15
-rw-r--r--pimd/pim_ifchannel.c75
-rw-r--r--pimd/pim_ifchannel.h6
-rw-r--r--pimd/pim_join.c106
-rw-r--r--pimd/pim_jp_agg.c39
-rw-r--r--pimd/pim_macro.c8
-rw-r--r--pimd/pim_msg.c88
-rw-r--r--pimd/pim_msg.h57
-rw-r--r--pimd/pim_neighbor.c137
-rw-r--r--pimd/pim_neighbor.h6
-rw-r--r--pimd/pim_nht.c40
-rw-r--r--pimd/pim_pim.c2
-rw-r--r--pimd/pim_pim.h4
-rw-r--r--pimd/pim_register.c23
-rw-r--r--pimd/pim_rp.c97
-rw-r--r--pimd/pim_rp.h8
-rw-r--r--pimd/pim_rpf.c26
-rw-r--r--pimd/pim_ssm.c9
-rw-r--r--pimd/pim_ssm.h2
-rw-r--r--pimd/pim_tlv.c228
-rw-r--r--pimd/pim_tlv.h20
-rw-r--r--pimd/pim_upstream.c43
-rw-r--r--pimd/pim_util.c8
-rw-r--r--pimd/pim_util.h2
-rw-r--r--pimd/pim_vty.c10
-rw-r--r--pimd/pim_vxlan.c4
-rw-r--r--pimd/pim_zebra.c46
-rw-r--r--pimd/pim_zlookup.c6
-rw-r--r--pimd/pimd.c14
-rw-r--r--pimd/pimd.h2
-rw-r--r--tests/bgpd/test_aspath.c12
-rw-r--r--tests/topotests/bgp_route_map/test_route_map_topo1.py21
-rw-r--r--tests/topotests/lib/bgp.py2
-rw-r--r--tests/topotests/lib/ospf.py19
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py4
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_authentication.json169
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py1446
-rwxr-xr-xvtysh/extract.pl.in2
-rw-r--r--vtysh/vtysh.c6
-rw-r--r--vtysh/vtysh.h2
-rw-r--r--vtysh/vtysh_main.c2
-rw-r--r--yang/frr-pathd.yang2
-rw-r--r--zebra/debug_nl.c216
-rw-r--r--zebra/ioctl.c25
-rw-r--r--zebra/kernel_netlink.c127
-rw-r--r--zebra/kernel_socket.c14
-rw-r--r--zebra/rt.h4
-rw-r--r--zebra/rt_netlink.h2
-rw-r--r--zebra/zebra_router.c6
104 files changed, 5150 insertions, 1107 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 192cd6ca82..dd27c9f6a1 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -328,7 +328,12 @@ void aspath_free(struct aspath *aspath)
void aspath_unintern(struct aspath **aspath)
{
struct aspath *ret;
- struct aspath *asp = *aspath;
+ struct aspath *asp;
+
+ if (!*aspath)
+ return;
+
+ asp = *aspath;
if (asp->refcnt)
asp->refcnt--;
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 4f25f2284f..21f92c353e 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1086,8 +1086,7 @@ void bgp_attr_unintern_sub(struct attr *attr)
struct lcommunity *lcomm = NULL;
/* aspath refcount shoud be decrement. */
- if (attr->aspath)
- aspath_unintern(&attr->aspath);
+ aspath_unintern(&attr->aspath);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
if (attr->community)
@@ -3494,14 +3493,12 @@ done:
* we can chuck as4_aggregator and as4_path alltogether in order
* to save memory
*/
- if (as4_path) {
- /*
- * unintern - it is in the hash
- * The flag that we got this is still there, but that
- * does not do any trouble
- */
- aspath_unintern(&as4_path);
- }
+ /*
+ * unintern - it is in the hash
+ * The flag that we got this is still there, but that
+ * does not do any trouble
+ */
+ aspath_unintern(&as4_path);
transit = bgp_attr_get_transit(attr);
if (ret != BGP_ATTR_PARSE_ERROR) {
diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c
index 0f9d5fc73a..f11717b41f 100644
--- a/bgpd/bgp_errors.c
+++ b/bgpd/bgp_errors.c
@@ -464,7 +464,7 @@ static struct log_ref ferr_bgp_err[] = {
},
{
.code = EC_BGP_INVALID_BGP_INSTANCE,
- .title = "BGP instance for the specifc vrf is invalid",
+ .title = "BGP instance for the specific vrf is invalid",
.description = "Indicates that specified bgp instance is NULL",
.suggestion = "Get log files from router and open an issue",
},
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index b5012e4586..eafc37f20c 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -526,7 +526,7 @@ static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
struct prefix_ipv6 *chunk;
struct in6_addr sid_buf;
bool alloced = false;
- int label;
+ int label = 0;
if (!bgp || !sid)
return false;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 66c5d862a6..8311cb207c 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2219,8 +2219,16 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* implementations.
*/
if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
- if (!bgp_outbound_policy_exists(peer, filter))
+ if (!bgp_outbound_policy_exists(peer, filter)) {
+ if (monotime_since(&bgp->ebgprequirespolicywarning,
+ NULL) > FIFTEENMINUTE2USEC ||
+ bgp->ebgprequirespolicywarning.tv_sec == 0) {
+ zlog_warn(
+ "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
+ monotime(&bgp->ebgprequirespolicywarning);
+ }
return false;
+ }
/* draft-ietf-idr-deprecate-as-set-confed-set
* Filter routes having AS_SET or AS_CONFED_SET in the path.
@@ -3844,6 +3852,13 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (!bgp_inbound_policy_exists(peer,
&peer->filter[afi][safi])) {
reason = "inbound policy missing";
+ if (monotime_since(&bgp->ebgprequirespolicywarning,
+ NULL) > FIFTEENMINUTE2USEC ||
+ bgp->ebgprequirespolicywarning.tv_sec == 0) {
+ zlog_warn(
+ "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
+ monotime(&bgp->ebgprequirespolicywarning);
+ }
goto filtered;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 9a1991cd09..afe4c7ae6f 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -803,11 +803,15 @@ struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str)
return NULL;
}
-int bgp_vty_return(struct vty *vty, int ret)
+int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
{
const char *str = NULL;
switch (ret) {
+ case BGP_SUCCESS:
+ case BGP_CREATED:
+ case BGP_GR_NO_OPERATION:
+ break;
case BGP_ERR_INVALID_VALUE:
str = "Invalid value";
break;
@@ -877,6 +881,36 @@ int bgp_vty_return(struct vty *vty, int ret)
case BGP_ERR_GR_OPERATION_FAILED:
str = "The Graceful Restart Operation failed due to an err.";
break;
+ case BGP_ERR_PEER_GROUP_MEMBER:
+ str = "Peer-group member cannot override remote-as of peer-group.";
+ break;
+ case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
+ str = "Peer-group members must be all internal or all external.";
+ break;
+ case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND:
+ str = "Range specified cannot be deleted because it is not part of current config.";
+ break;
+ case BGP_ERR_INSTANCE_MISMATCH:
+ str = "Instance specified does not match the current instance.";
+ break;
+ case BGP_ERR_NO_INTERFACE_CONFIG:
+ str = "Interface specified is not being used for interface based peer.";
+ break;
+ case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
+ str = "No configuration already specified for soft reconfiguration.";
+ break;
+ case BGP_ERR_AS_MISMATCH:
+ str = "BGP is already running.";
+ break;
+ case BGP_ERR_AF_UNCONFIGURED:
+ str = "AFI/SAFI specified is not currently configured.";
+ break;
+ case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS:
+ str = "AS specified for local as is the same as the remote as and this is not allowed.";
+ break;
+ case BGP_ERR_INVALID_AS:
+ str = "Confederation AS specified is the same AS as our AS.";
+ break;
}
if (str) {
vty_out(vty, "%% %s\n", str);
@@ -4211,17 +4245,6 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
ret = peer_remote_as(bgp, &su, NULL, &as, as_type);
}
- /* This peer belongs to peer group. */
- switch (ret) {
- case BGP_ERR_PEER_GROUP_MEMBER:
- vty_out(vty,
- "%% Peer-group member cannot override remote-as of peer-group\n");
- return CMD_WARNING_CONFIG_FAILED;
- case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
- vty_out(vty,
- "%% Peer-group members must be all internal or all external\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
return bgp_vty_return(vty, ret);
}
@@ -4958,13 +4981,6 @@ DEFUN (neighbor_set_peer_group,
ret = peer_group_bind(bgp, &su, peer, group, &as);
- if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) {
- vty_out(vty,
- "%% Peer with AS %u cannot be in this peer-group, members must be all internal or all external\n",
- as);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return bgp_vty_return(vty, ret);
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index e6d4000ad8..43046f7f18 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -651,9 +651,6 @@ int bgp_confederation_peers_add(struct bgp *bgp, as_t as)
struct peer *peer;
struct listnode *node, *nnode;
- if (!bgp)
- return BGP_ERR_INVALID_BGP;
-
if (bgp->as == as)
return BGP_ERR_INVALID_AS;
@@ -3239,6 +3236,10 @@ static struct bgp *bgp_create(as_t *as, const char *name,
/*initilize global GR FSM */
bgp_global_gr_init(bgp);
+
+ memset(&bgp->ebgprequirespolicywarning, 0,
+ sizeof(bgp->ebgprequirespolicywarning));
+
return bgp;
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index ae6427b356..8b93c450e8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -759,6 +759,9 @@ struct bgp {
struct list *srv6_locator_chunks;
struct list *srv6_functions;
+ struct timeval ebgprequirespolicywarning;
+#define FIFTEENMINUTE2USEC (int64_t)15 * 60 * 1000000
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp);
@@ -1916,46 +1919,46 @@ enum bgp_clear_type {
(((S) == OpenSent) || ((S) == OpenConfirm) || ((S) == Established))
/* BGP error codes. */
-#define BGP_SUCCESS 0
-#define BGP_CREATED 1
-#define BGP_ERR_INVALID_VALUE -1
-#define BGP_ERR_INVALID_FLAG -2
-#define BGP_ERR_INVALID_AS -3
-#define BGP_ERR_INVALID_BGP -4
-#define BGP_ERR_PEER_GROUP_MEMBER -5
-#define BGP_ERR_PEER_GROUP_NO_REMOTE_AS -7
-#define BGP_ERR_PEER_GROUP_CANT_CHANGE -8
-#define BGP_ERR_PEER_GROUP_MISMATCH -9
-#define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT -10
-#define BGP_ERR_AS_MISMATCH -12
-#define BGP_ERR_PEER_FLAG_CONFLICT -13
-#define BGP_ERR_PEER_GROUP_SHUTDOWN -14
-#define BGP_ERR_PEER_FILTER_CONFLICT -15
-#define BGP_ERR_NOT_INTERNAL_PEER -16
-#define BGP_ERR_REMOVE_PRIVATE_AS -17
-#define BGP_ERR_AF_UNCONFIGURED -18
-#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -19
-#define BGP_ERR_INSTANCE_MISMATCH -20
-#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -21
-#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -22
-#define BGP_ERR_TCPSIG_FAILED -23
-#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -24
-#define BGP_ERR_NO_IBGP_WITH_TTLHACK -25
-#define BGP_ERR_NO_INTERFACE_CONFIG -26
-#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -27
-#define BGP_ERR_AS_OVERRIDE -28
-#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -29
-#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -30
-#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -31
-#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -32
-#define BGP_ERR_MAX -33
-#define BGP_ERR_INVALID_FOR_DIRECT_PEER -34
-#define BGP_ERR_PEER_SAFI_CONFLICT -35
-
-/* BGP GR ERRORS */
-#define BGP_ERR_GR_INVALID_CMD -36
-#define BGP_ERR_GR_OPERATION_FAILED -37
-#define BGP_GR_NO_OPERATION -38
+enum bgp_create_error_code {
+ BGP_SUCCESS = 0,
+ BGP_CREATED = 1,
+ BGP_ERR_INVALID_VALUE = -1,
+ BGP_ERR_INVALID_FLAG = -2,
+ BGP_ERR_INVALID_AS = -3,
+ BGP_ERR_PEER_GROUP_MEMBER = -4,
+ BGP_ERR_PEER_GROUP_NO_REMOTE_AS = -5,
+ BGP_ERR_PEER_GROUP_CANT_CHANGE = -6,
+ BGP_ERR_PEER_GROUP_MISMATCH = -7,
+ BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT = -8,
+ BGP_ERR_AS_MISMATCH = -9,
+ BGP_ERR_PEER_FLAG_CONFLICT = -10,
+ BGP_ERR_PEER_GROUP_SHUTDOWN = -11,
+ BGP_ERR_PEER_FILTER_CONFLICT = -12,
+ BGP_ERR_NOT_INTERNAL_PEER = -13,
+ BGP_ERR_REMOVE_PRIVATE_AS = -14,
+ BGP_ERR_AF_UNCONFIGURED = -15,
+ BGP_ERR_SOFT_RECONFIG_UNCONFIGURED = -16,
+ BGP_ERR_INSTANCE_MISMATCH = -17,
+ BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP = -18,
+ BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS = -19,
+ BGP_ERR_TCPSIG_FAILED = -20,
+ BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK = -21,
+ BGP_ERR_NO_IBGP_WITH_TTLHACK = -22,
+ BGP_ERR_NO_INTERFACE_CONFIG = -23,
+ BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS = -24,
+ BGP_ERR_AS_OVERRIDE = -25,
+ BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT = -26,
+ BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS = -27,
+ BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND = -28,
+ BGP_ERR_INVALID_FOR_DYNAMIC_PEER = -29,
+ BGP_ERR_INVALID_FOR_DIRECT_PEER = -30,
+ BGP_ERR_PEER_SAFI_CONFLICT = -31,
+
+ /* BGP GR ERRORS */
+ BGP_ERR_GR_INVALID_CMD = -32,
+ BGP_ERR_GR_OPERATION_FAILED = -33,
+ BGP_GR_NO_OPERATION = -34,
+};
/*
* Enumeration of different policy kinds a peer can be configured with.
diff --git a/configure.ac b/configure.ac
index e7bbe329b1..bdddf4b846 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2587,6 +2587,7 @@ AC_DEFINE_UNQUOTED([ZEBRA_SERV_PATH], ["$frr_statedir%s%s/zserv.api"], [zebra ap
AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir%s%s/bfdd.sock"], [bfdd control socket])
AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$frr_statedir%s/ospfd-gr.json"], [ospfd GR state information])
AC_DEFINE_UNQUOTED([OSPF6D_GR_STATE], ["$frr_statedir/ospf6d-gr.json"], [ospf6d GR state information])
+AC_DEFINE_UNQUOTED([OSPF6_AUTH_SEQ_NUM_FILE], ["$frr_statedir/ospf6d-at-seq-no.dat"], [ospf6d AT Sequence number information])
AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory])
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 2005e9d8bb..45bee17b71 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -141,6 +141,16 @@ March/July/November. Walking backwards from this date:
- 2 weeks earlier, a ``frr-X.Y-rc`` release candidate is tagged.
+ .. code-block:: console
+
+ % git remote --verbose
+ upstream git@github.com:frrouting/frr (fetch)
+ upstream git@github.com:frrouting/frr (push)
+
+ % git checkout dev/8.2
+ % git tag frr-8.2-rc
+ % git push upstream frr-8.2-rc
+
- on release date, the branch is renamed to ``stable/MAJOR.MINOR``.
The 2 week window between each of these events should be used to run any and
diff --git a/doc/manpages/vtysh.rst b/doc/manpages/vtysh.rst
index b930cb915d..af527bea40 100644
--- a/doc/manpages/vtysh.rst
+++ b/doc/manpages/vtysh.rst
@@ -74,7 +74,7 @@ VTYSH_PAGER
VTYSH_HISTFILE
Override the history file for vtysh commands. Logging can be turned off using ``VTYSH_HISTFILE=/dev/null vtysh``.
- Environment is prefered way to override the history file path over command line argument (-H/--histfile).
+ Environment is preferred way to override the history file path over command line argument (-H/--histfile).
FILES
=====
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 624510323c..8dacb9c9dc 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -383,6 +383,256 @@ Graceful Restart
This is an EXEC-level command.
+.. _Authentication-trailer:
+
+Authentication trailer support:
+===============================
+IPv4 version of OSPF supports authentication as part of the base RFC.
+When IPv6 version of OSPF was developed there was IPSec support for IPv6,
+Hence OSPFv3(IPv6 version of OSPF) suggest to use IPSec as authentication
+and encryption mechanism. IPSec supports authentication using AH header and
+Encryption using ESP.
+
+There are few disadvantages of using IPSec with OSPFv3.
+ 1. If encryption is enabled for OSPFv3 packets, then its not
+ possible to give priority to control packets.
+ 2. IPSec has platform dependency and may not be supported
+ in all platforms.
+ 3. It is performance intensive.
+ 4. Its difficult to configure.
+
+
+Some advantages of OSPFv3 authentication trailer feature.
+ 1. It provides replay protection via sequence number.
+ 2. It provides IPv6 source address protection.
+ 3. No platform dependency.
+ 4. Easy to implement and maintain.
+
+
+This feature is support for ``RFC7166``.
+
+FRR supports MD5 and SHA256 internally and relays on openssl for other hash
+algorithms. If user wants to use only MD5 and SHA256, no special action is
+required. If user wants complete support of authentication trailer with all
+hash algorithms follow below steps.
+
+
+Installing Dependencies:
+------------------------
+
+.. code-block:: console
+
+ sudo apt update
+ sudo apt-get install openssl
+
+
+Compile:
+--------
+Follow normal compilation as mentioned in the build page. If you want to
+use all the hash algorithms then follow the steps mentioned in note before
+compiling.
+
+
+.. note::
+
+ If your platform supports ``openssl``, please make sure to add
+ ``--with-crypto=openssl`` to your configure options.
+ Default value is ``--with-crypto=internal``
+
+
+CLI Configuration:
+------------------
+There are two ways in which authentication trailer can be configured for
+OSPFv3. These commands are mutually exclusive, only one can be configured
+at any time.
+
+ 1. Using manual key configuration.
+ 2. Using keychain.
+
+
+List of hash algorithms supported:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Without openssl:
+++++++++++++++++
+ ``MD5``
+ ``HMAC-SHA-256``
+
+
+With openssl:
++++++++++++++
+ ``MD5``
+ ``HMAC-SHA-1``
+ ``HMAC-SHA-256``
+ ``HMAC-SHA-384``
+ ``HMAC-SHA-512``
+
+
+Example configuration of manual key:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Without openssl:
+++++++++++++++++
+
+.. clicmd:: ipv6 ospf6 authentication key-id (1-65535) hash-algo <md5|hmac-sha-256> key WORD
+
+With openssl:
++++++++++++++
+
+.. clicmd:: ipv6 ospf6 authentication key-id (1-65535) hash-algo <md5|hmac-sha-256|hmac-sha-1|hmac-sha-384|hmac-sha-512> key WORD
+
+
+Example configuration of keychain:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. clicmd:: ipv6 ospf6 authentication keychain KEYCHAIN_NAME
+
+
+Running configuration:
+----------------------
+
+Manual key:
+^^^^^^^^^^^
+
+.. code-block:: frr
+
+ frr# show running-config
+ Building configuration...
+
+ Current configuration:
+ !
+ interface ens192
+ ipv6 address 2001:DB8::2/64
+ ipv6 ospf6 authentication key-id 10 hash-algo hmac-sha-256 key abhinay
+
+Keychain:
+^^^^^^^^^
+
+.. code-block:: frr
+
+ frr# show running-config
+ Building configuration...
+
+ Current configuration:
+ !
+ interface ens192
+ ipv6 address 2001:DB8::2/64
+ ipv6 ospf6 authentication keychain abhinay
+
+
+Example keychain config:
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: frr
+
+ frr#show running-config
+ Building configuration...
+
+ Current configuration:
+ !
+ key chain abcd
+ key 100
+ key-string password
+ cryptographic-algorithm sha1
+ exit
+ key 200
+ key-string password
+ cryptographic-algorithm sha256
+ exit
+ !
+ key chain pqr
+ key 300
+ key-string password
+ cryptographic-algorithm sha384
+ exit
+ key 400
+ key-string password
+ cryptographic-algorithm sha384
+ exit
+ !
+
+Show commands:
+--------------
+There is an interface show command that displays if authentication trailer
+is enabled or not. json output is also supported.
+
+There is support for drop counters, which will help in debugging the feature.
+
+.. code-block:: frr
+
+ frr# show ipv6 ospf6 interface ens192
+ ens192 is up, type BROADCAST
+ Interface ID: 5
+ Number of I/F scoped LSAs is 2
+ 0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
+ 0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
+ Authentication trailer is enabled with manual key ==> new info added
+ Packet drop Tx 0, Packet drop Rx 0
+
+
+OSPFv3 supports options in hello and database description packets hence
+the presence of authentication trailer needs to be stored in OSPFv3
+neighbor info. Since RFC specifies that we need to handled sequence number
+for every ospf6 packet type, sequence number recvd in authentication header
+from the neighbor is stored in neighbor to validate the packet.
+json output is also supported.
+
+.. code-block:: frr
+
+ frr# show ipv6 ospf6 neighbor 2.2.2.2 detail
+ Neighbor 2.2.2.2%ens192
+ Area 1 via interface ens192 (ifindex 3)
+ 0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
+ 0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
+ Authentication header present ==> new info added
+ hello DBDesc LSReq LSUpd LSAck
+ Higher sequence no 0x0 0x0 0x0 0x0 0x0
+ Lower sequence no 0x242E 0x1DC4 0x1DC3 0x23CC 0x1DDA
+
+Sent packet sequence number is maintained per ospf6 router for every packet
+that is sent out of router, so sequence number is maintained per ospf6 process.
+
+.. code-block:: frr
+
+ frr# show ipv6 ospf6
+ OSPFv3 Routing Process (0) with Router-ID 2.2.2.2
+ Number of areas in this router is 1
+ Authentication Sequence number info
+ Higher sequence no 3, Lower sequence no 1656
+
+Debug command:
+--------------
+Below command can be used to enable ospfv3 authentication trailer
+specific logs if you have to debug the feature.
+
+.. clicmd:: debug ospf6 authentication [<tx|rx>]
+
+Feature supports authentication trailer tx/rx drop counters for debugging,
+which can be used to see if packets are getting dropped due to error in
+processing authentication trailer information in OSPFv3 packet.
+json output is also supported.
+
+.. code-block:: frr
+
+ frr# show ipv6 ospf6 interface ens192
+ ens192 is up, type BROADCAST
+ Interface ID: 5
+ Number of I/F scoped LSAs is 2
+ 0 Pending LSAs for LSUpdate in Time 00:00:00 [thread off]
+ 0 Pending LSAs for LSAck in Time 00:00:00 [thread off]
+ Authentication trailer is enabled with manual key
+ Packet drop Tx 0, Packet drop Rx 0 ==> new counters
+
+Clear command:
+--------------
+Below command can be used to clear the tx/rx drop counters in interface.
+Below command can be used to clear all ospfv3 interface or specific
+interface by specifying the interface name.
+
+.. clicmd:: clear ipv6 ospf6 auth-counters interface [IFNAME]
+
+
+
.. _showing-ospf6-information:
Showing OSPF6 information
@@ -431,7 +681,7 @@ Showing OSPF6 information
.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] interface traffic [json]
- Shows counts of different packets that have been recieved and transmitted
+ Shows counts of different packets that have been received and transmitted
by the interfaces. JSON output can be obtained by appending "json" at the
end.
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index ed4d02d89b..d1a0bb6f7b 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -268,8 +268,10 @@ To start OSPF process you have to specify the OSPF router.
the destination prefix. Otherwise, we test whether the network command prefix
contains the local address prefix of the interface.
- In some cases it may be more convenient to enable OSPF on a per
- interface/subnet basis (:clicmd:`ip ospf area AREA [ADDR]`).
+ It is also possible to enable OSPF on a per interface/subnet basis
+ using the interface command (:clicmd:`ip ospf area AREA [ADDR]`).
+ However, mixing both network commands (:clicmd:`network`) and interface
+ commands (:clicmd:`ip ospf`) on the same router is not supported.
.. clicmd:: proactive-arp
@@ -313,9 +315,9 @@ To start OSPF process you have to specify the OSPF router.
Areas
-----
-.. clicmd:: area A.B.C.D range A.B.C.D/M
+.. clicmd:: area A.B.C.D range A.B.C.D/M [advertise [cost (0-16777215)]]
-.. clicmd:: area (0-4294967295) range A.B.C.D/M
+.. clicmd:: area (0-4294967295) range A.B.C.D/M [advertise [cost (0-16777215)]]
@@ -346,9 +348,9 @@ Areas
range are not advertised into other areas.
This command makes sense in ABR only.
-.. clicmd:: area A.B.C.D range A.B.C.D/M substitute A.B.C.D/M
+.. clicmd:: area A.B.C.D range A.B.C.D/M {substitute A.B.C.D/M|cost (0-16777215)}
-.. clicmd:: area (0-4294967295) range A.B.C.D/M substitute A.B.C.D/M
+.. clicmd:: area (0-4294967295) range A.B.C.D/M {substitute A.B.C.D/M|cost (0-16777215)}
Substitute summarized prefix with another prefix.
@@ -364,6 +366,11 @@ Areas
One Type-3 summary-LSA with routing info 11.0.0.0/8 is announced into backbone area if
area 0.0.0.10 contains at least one intra-area network (i.e. described with router-LSA or
network-LSA) from range 10.0.0.0/8.
+
+ By default, the metric of the summary route is calculated as the highest
+ metric among the summarized routes. The `cost` option, however, can be used
+ to set an explicit metric.
+
This command makes sense in ABR only.
.. clicmd:: area A.B.C.D virtual-link A.B.C.D
@@ -510,12 +517,14 @@ Interfaces
Enable OSPF on the interface, optionally restricted to just the IP address
- given by `ADDR`, putting it in the `AREA` area. Per interface area settings
- take precedence to network commands
- (:clicmd:`network A.B.C.D/M area A.B.C.D`).
-
- If you have a lot of interfaces, and/or a lot of subnets, then enabling OSPF
- via this command may result in a slight performance improvement.
+ given by `ADDR`, putting it in the `AREA` area. If you have a lot of
+ interfaces, and/or a lot of subnets, then enabling OSPF via this command
+ instead of (:clicmd:`network A.B.C.D/M area A.B.C.D`) may result in a
+ slight performance improvement.
+
+ Notice that, mixing both network commands (:clicmd:`network`) and interface
+ commands (:clicmd:`ip ospf`) on the same router is not supported.
+ If (:clicmd:`ip ospf`) is present, (:clicmd:`network`) commands will fail.
.. clicmd:: ip ospf authentication-key AUTH_KEY
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 306feec0f7..1c3a0110ac 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -176,7 +176,7 @@ Certain signals have special meanings to *pimd*.
Generate IGMP query (v2/v3) on user requirement. This will not depend on
the existing IGMP general query timer.If no version is provided in the cli,
- it will be considered as default v2 query.This is a hidden command.
+ the default will be the igmp version enabled on that interface.
.. clicmd:: ip igmp watermark-warn (1-65535)
@@ -393,7 +393,7 @@ cause great confusion.
Display IGMP group retransmission information.
-.. clicmd:: show ip igmp sources
+.. clicmd:: show ip igmp [vrf NAME] sources [json]
Display IGMP sources information.
diff --git a/lib/keychain.c b/lib/keychain.c
index 02f83ef0a8..c29c45a114 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
#include <zebra.h>
#include "command.h"
@@ -207,6 +208,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index)
key = key_new();
key->index = index;
+ key->hash_algo = KEYCHAIN_ALGO_NULL;
listnode_add_sort(keychain->key, key);
return key;
@@ -336,6 +338,133 @@ DEFUN (no_key_string,
return CMD_SUCCESS;
}
+const struct keychain_algo_info algo_info[] = {
+ {KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"},
+ {KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE,
+ KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE, "MD5"},
+ {KEYCHAIN_ALGO_HMAC_SHA1, "hmac-sha-1", KEYCHAIN_HMAC_SHA1_HASH_SIZE,
+ KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE, "HMAC-SHA-1"},
+ {KEYCHAIN_ALGO_HMAC_SHA256, "hmac-sha-256",
+ KEYCHAIN_HMAC_SHA256_HASH_SIZE, KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE,
+ "HMAC-SHA-256"},
+ {KEYCHAIN_ALGO_HMAC_SHA384, "hmac-sha-384",
+ KEYCHAIN_HMAC_SHA384_HASH_SIZE, KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE,
+ "HMAC-SHA-384"},
+ {KEYCHAIN_ALGO_HMAC_SHA512, "hmac-sha-512",
+ KEYCHAIN_HMAC_SHA512_HASH_SIZE, KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE,
+ "HMAC-SHA-512"},
+ {KEYCHAIN_ALGO_MAX, "max", KEYCHAIN_MAX_HASH_SIZE,
+ KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE, "Not defined"}
+};
+
+uint16_t keychain_get_block_size(enum keychain_hash_algo key)
+{
+ return algo_info[key].block;
+}
+
+uint16_t keychain_get_hash_len(enum keychain_hash_algo key)
+{
+ return algo_info[key].length;
+}
+
+const char *keychain_get_description(enum keychain_hash_algo key)
+{
+ return algo_info[key].desc;
+}
+
+struct keychain_algo_info
+keychain_get_hash_algo_info(enum keychain_hash_algo key)
+{
+ return algo_info[key];
+}
+
+enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name)
+{
+#ifdef CRYPTO_INTERNAL
+ if (!strncmp(name, "hmac-sha-2", 10))
+ return KEYCHAIN_ALGO_HMAC_SHA256;
+ else if (!strncmp(name, "m", 1))
+ return KEYCHAIN_ALGO_MD5;
+ else
+ return KEYCHAIN_ALGO_NULL;
+#else
+ if (!strncmp(name, "m", 1))
+ return KEYCHAIN_ALGO_MD5;
+ else if (!strncmp(name, "hmac-sha-1", 10))
+ return KEYCHAIN_ALGO_HMAC_SHA1;
+ else if (!strncmp(name, "hmac-sha-2", 10))
+ return KEYCHAIN_ALGO_HMAC_SHA256;
+ else if (!strncmp(name, "hmac-sha-3", 10))
+ return KEYCHAIN_ALGO_HMAC_SHA384;
+ else if (!strncmp(name, "hmac-sha-5", 10))
+ return KEYCHAIN_ALGO_HMAC_SHA512;
+ else
+ return KEYCHAIN_ALGO_NULL;
+#endif
+}
+
+const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key)
+{
+ return algo_info[key].name;
+}
+
+DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd,
+ "cryptographic-algorithm "
+ "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>",
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n")
+{
+ int algo_idx = 1;
+ uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
+
+ VTY_DECLVAR_CONTEXT_SUB(key, key);
+ hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
+#ifndef CRYPTO_OPENSSL
+ if (hash_algo == KEYCHAIN_ALGO_NULL) {
+ vty_out(vty,
+ "Hash algorithm not supported, compile with --with-crypto=openssl\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+#endif /* CRYPTO_OPENSSL */
+ key->hash_algo = hash_algo;
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd,
+ "no cryptographic-algorithm "
+ "[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>]",
+ NO_STR
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n")
+{
+ int algo_idx = 2;
+ uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
+
+ VTY_DECLVAR_CONTEXT_SUB(key, key);
+ if (argc > algo_idx) {
+ hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
+ if (hash_algo == KEYCHAIN_ALGO_NULL) {
+ vty_out(vty,
+ "Hash algorithm not supported, try compiling with --with-crypto=openssl\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo))
+ return CMD_SUCCESS;
+
+ key->hash_algo = KEYCHAIN_ALGO_NULL;
+ return CMD_SUCCESS;
+}
+
/* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when
given string is malformed. */
static time_t key_str2time(const char *time_str, const char *day_str,
@@ -1004,6 +1133,11 @@ static int keychain_config_write(struct vty *vty)
if (key->string)
vty_out(vty, " key-string %s\n", key->string);
+ if (key->hash_algo != KEYCHAIN_ALGO_NULL)
+ vty_out(vty, " cryptographic-algorithm %s\n",
+ keychain_get_algo_name_by_id(
+ key->hash_algo));
+
if (key->accept.start) {
keychain_strftime(buf, BUFSIZ,
&key->accept.start);
@@ -1051,10 +1185,29 @@ static int keychain_config_write(struct vty *vty)
return 0;
}
+
+static void keychain_active_config(vector comps, struct cmd_token *token)
+{
+ struct keychain *keychain;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain))
+ vector_set(comps, XSTRDUP(MTYPE_COMPLETION, keychain->name));
+}
+
+static const struct cmd_variable_handler keychain_var_handlers[] = {
+ {.varname = "key_chain", .completions = keychain_active_config},
+ {.tokenname = "KEYCHAIN_NAME", .completions = keychain_active_config},
+ {.tokenname = "KCHAIN_NAME", .completions = keychain_active_config},
+ {.completions = NULL}
+};
+
void keychain_init(void)
{
keychain_list = list_new();
+ /* Register handler for keychain auto config support */
+ cmd_variable_handler_register(keychain_var_handlers);
install_node(&keychain_node);
install_node(&keychain_key_node);
@@ -1113,4 +1266,6 @@ void keychain_init(void)
install_element(KEYCHAIN_KEY_NODE,
&send_lifetime_duration_month_day_cmd);
install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd);
}
diff --git a/lib/keychain.h b/lib/keychain.h
index eb6d2f175e..71319d9722 100644
--- a/lib/keychain.h
+++ b/lib/keychain.h
@@ -27,6 +27,47 @@
extern "C" {
#endif
+enum keychain_hash_algo {
+ KEYCHAIN_ALGO_NULL,
+ KEYCHAIN_ALGO_MD5,
+ KEYCHAIN_ALGO_HMAC_SHA1,
+ KEYCHAIN_ALGO_HMAC_SHA256,
+ KEYCHAIN_ALGO_HMAC_SHA384,
+ KEYCHAIN_ALGO_HMAC_SHA512,
+ KEYCHAIN_ALGO_MAX
+};
+
+#define KEYCHAIN_MD5_HASH_SIZE 16
+#define KEYCHAIN_HMAC_SHA1_HASH_SIZE 20
+#define KEYCHAIN_HMAC_SHA256_HASH_SIZE 32
+#define KEYCHAIN_HMAC_SHA384_HASH_SIZE 48
+#define KEYCHAIN_HMAC_SHA512_HASH_SIZE 64
+#define KEYCHAIN_MAX_HASH_SIZE 64
+
+#define KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE 16
+#define KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE 64
+#define KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE 64
+#define KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE 128
+#define KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE 128
+#define KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE 128
+
+struct keychain_algo_info {
+ enum keychain_hash_algo key;
+ const char *name;
+ uint16_t length;
+ uint16_t block;
+ const char *desc;
+};
+
+extern const struct keychain_algo_info algo_info[];
+uint16_t keychain_get_block_size(enum keychain_hash_algo key);
+uint16_t keychain_get_hash_len(enum keychain_hash_algo key);
+const char *keychain_get_description(enum keychain_hash_algo key);
+struct keychain_algo_info
+keychain_get_hash_algo_info(enum keychain_hash_algo key);
+enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name);
+const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key);
+
struct keychain {
char *name;
@@ -47,7 +88,7 @@ struct key {
uint32_t index;
char *string;
-
+ enum keychain_hash_algo hash_algo;
struct key_range send;
struct key_range accept;
@@ -60,7 +101,7 @@ extern struct keychain *keychain_lookup(const char *);
extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t);
extern struct key *key_match_for_accept(const struct keychain *, const char *);
extern struct key *key_lookup_for_send(const struct keychain *);
-
+const char *keychain_algo_str(enum keychain_hash_algo hash_algo);
#ifdef __cplusplus
}
#endif
diff --git a/lib/thread.c b/lib/thread.c
index 376f61c247..ada7a9cc80 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -138,11 +138,12 @@ static void cpu_record_hash_free(void *a)
static void vty_out_cpu_thread_history(struct vty *vty,
struct cpu_thread_history *a)
{
- vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu %9zu %9zu",
+ vty_out(vty,
+ "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu %9zu %9zu %10zu",
a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
(a->real.total / a->total_calls), a->real.max,
- a->total_cpu_warn, a->total_wall_warn);
+ a->total_cpu_warn, a->total_wall_warn, a->total_starv_warn);
vty_out(vty, " %c%c%c%c%c %s\n",
a->types & (1 << THREAD_READ) ? 'R' : ' ',
a->types & (1 << THREAD_WRITE) ? 'W' : ' ',
@@ -168,6 +169,8 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
atomic_load_explicit(&a->total_cpu_warn, memory_order_seq_cst);
copy.total_wall_warn =
atomic_load_explicit(&a->total_wall_warn, memory_order_seq_cst);
+ copy.total_starv_warn = atomic_load_explicit(&a->total_starv_warn,
+ memory_order_seq_cst);
copy.cpu.total =
atomic_load_explicit(&a->cpu.total, memory_order_seq_cst);
copy.cpu.max = atomic_load_explicit(&a->cpu.max, memory_order_seq_cst);
@@ -186,6 +189,7 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
totals->total_calls += copy.total_calls;
totals->total_cpu_warn += copy.total_cpu_warn;
totals->total_wall_warn += copy.total_wall_warn;
+ totals->total_starv_warn += copy.total_starv_warn;
totals->real.total += copy.real.total;
if (totals->real.max < copy.real.max)
totals->real.max = copy.real.max;
@@ -231,7 +235,8 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
vty_out(vty,
"Active Runtime(ms) Invoked Avg uSec Max uSecs");
vty_out(vty, " Avg uSec Max uSecs");
- vty_out(vty, " CPU_Warn Wall_Warn Type Thread\n");
+ vty_out(vty,
+ " CPU_Warn Wall_Warn Starv_Warn Type Thread\n");
if (m->cpu_record->count)
hash_iterate(
@@ -1668,13 +1673,17 @@ static unsigned int thread_process_timers(struct thread_master *m,
* really getting behind on handling of events.
* Let's log it and do the right thing with it.
*/
- if (!displayed && !thread->ignore_timer_late &&
- timercmp(timenow, &prev, >)) {
- flog_warn(
- EC_LIB_STARVE_THREAD,
- "Thread Starvation: %pTHD was scheduled to pop greater than 4s ago",
- thread);
- displayed = true;
+ if (timercmp(timenow, &prev, >)) {
+ atomic_fetch_add_explicit(
+ &thread->hist->total_starv_warn, 1,
+ memory_order_seq_cst);
+ if (!displayed && !thread->ignore_timer_late) {
+ flog_warn(
+ EC_LIB_STARVE_THREAD,
+ "Thread Starvation: %pTHD was scheduled to pop greater than 4s ago",
+ thread);
+ displayed = true;
+ }
}
thread_timer_list_pop(&m->timer);
diff --git a/lib/thread.h b/lib/thread.h
index 660f8bd28e..0c2a4ba869 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -137,6 +137,7 @@ struct cpu_thread_history {
int (*func)(struct thread *);
atomic_size_t total_cpu_warn;
atomic_size_t total_wall_warn;
+ atomic_size_t total_starv_warn;
atomic_size_t total_calls;
atomic_size_t total_active;
struct time_stats {
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 203ae14f2d..1c0d948cca 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -2874,7 +2874,7 @@ ospf6_originate_summary_lsa(struct ospf6 *ospf6,
if (IS_OSPF6_DEBUG_AGGR)
zlog_debug("%s: Aggr LSA ID: %d flags %x.",
__func__, aggr->id, aggr->aggrflags);
- /* Dont originate external LSA,
+ /* Don't originate external LSA,
* If it is configured not to advertise.
*/
if (CHECK_FLAG(aggr->aggrflags, OSPF6_EXTERNAL_AGGRT_NO_ADVERTISE)) {
@@ -3248,11 +3248,11 @@ static void ospf6_handle_aggregated_exnl_rt(struct ospf6 *ospf6,
/* Handling the case where the external route prefix
* and aggegate prefix is same
- * If same dont flush the originated external LSA.
+ * If same don't flush the originated external LSA.
*/
if (prefix_same(&aggr->p, &rt->prefix)) {
if (IS_OSPF6_DEBUG_AGGR)
- zlog_debug("%s: External Route prefix same as Aggregator(%pFX), so dont flush.",
+ zlog_debug("%s: External Route prefix same as Aggregator(%pFX), so don't flush.",
__func__,
&rt->prefix);
@@ -3623,7 +3623,7 @@ void ospf6_handle_external_lsa_origination(struct ospf6 *ospf6,
/* Handling the case where the
* external route prefix
* and aggegate prefix is same
- * If same dont flush the
+ * If same don't flush the
* originated
* external LSA.
*/
diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c
new file mode 100644
index 0000000000..1095473f4a
--- /dev/null
+++ b/ospf6d/ospf6_auth_trailer.c
@@ -0,0 +1,1000 @@
+/*
+ * Copyright (C) 2021 Abhinay Ramesh
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra 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.
+ *
+ * GNU Zebra 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 "config.h"
+#include "memory.h"
+#include "ospf6d.h"
+#include "vty.h"
+#include "command.h"
+#include "md5.h"
+#include "sha256.h"
+#include "lib/zlog.h"
+#include "ospf6_message.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_proto.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_auth_trailer.h"
+#include "ospf6_route.h"
+#include "ospf6_zebra.h"
+#include "lib/keychain.h"
+
+unsigned char conf_debug_ospf6_auth[2];
+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");
+
+/*Apad is the hexadecimal value 0x878FE1F3. */
+const uint8_t ospf6_hash_apad_max[KEYCHAIN_MAX_HASH_SIZE] = {
+ 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,
+ 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f,
+ 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87,
+ 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,
+ 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,
+ 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,
+};
+
+const uint8_t ospf6_hash_ipad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+};
+
+const uint8_t ospf6_hash_opad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+};
+
+void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length)
+{
+ struct ospf6_auth_hdr *ospf6_at_hdr;
+ uint16_t at_len, oh_len, at_hdr_len, hash_len;
+ unsigned char temp[KEYCHAIN_MAX_HASH_SIZE + 1];
+
+ oh_len = htons(ospfh->length);
+ at_len = length - oh_len;
+ if (at_len > 0) {
+ ospf6_at_hdr = (struct ospf6_auth_hdr *)
+ ((uint8_t *)ospfh + oh_len);
+ at_hdr_len = htons(ospf6_at_hdr->length);
+ hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;
+ memcpy(temp, ospf6_at_hdr->data, hash_len);
+ temp[hash_len] = '\0';
+ zlog_debug("OSPF6 Authentication Trailer");
+ zlog_debug(" Type %d", htons(ospf6_at_hdr->type));
+ zlog_debug(" Length %d", at_hdr_len);
+ zlog_debug(" Reserved %d", ospf6_at_hdr->reserved);
+ zlog_debug(" SA ID %d", htons(ospf6_at_hdr->id));
+ zlog_debug(" seqnum high 0x%08x",
+ htonl(ospf6_at_hdr->seqnum_h));
+ zlog_debug(" seqnum high 0x%08x",
+ htonl(ospf6_at_hdr->seqnum_l));
+ zlog_debug(" Data %s", temp);
+ }
+}
+
+void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length,
+ unsigned int lls_len)
+{
+ struct ospf6_auth_hdr *ospf6_at_hdr;
+ uint16_t at_len, oh_len, at_hdr_len, hash_len;
+ unsigned char temp[KEYCHAIN_MAX_HASH_SIZE + 1];
+
+ oh_len = ntohs(ospfh->length);
+ at_len = length - (oh_len + lls_len);
+ if (at_len > 0) {
+ ospf6_at_hdr =
+ (struct ospf6_auth_hdr *)((uint8_t *)ospfh + oh_len);
+ at_hdr_len = ntohs(ospf6_at_hdr->length);
+ hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;
+ memcpy(temp, ospf6_at_hdr->data, hash_len);
+ temp[hash_len] = '\0';
+ zlog_debug("OSPF6 Authentication Trailer");
+ zlog_debug(" Type %d", ntohs(ospf6_at_hdr->type));
+ zlog_debug(" Length %d", at_hdr_len);
+ zlog_debug(" Reserved %d", ospf6_at_hdr->reserved);
+ zlog_debug(" SA ID %d", ntohs(ospf6_at_hdr->id));
+ zlog_debug(" seqnum high 0x%08x",
+ ntohl(ospf6_at_hdr->seqnum_h));
+ zlog_debug(" seqnum high 0x%08x",
+ ntohl(ospf6_at_hdr->seqnum_l));
+ zlog_debug(" Data %s", temp);
+ }
+}
+
+unsigned char *ospf6_hash_message_xor(unsigned char *mes1,
+ unsigned char *mes2,
+ uint32_t len)
+{
+ unsigned char *result;
+ uint32_t i;
+
+ result = XCALLOC(MTYPE_OSPF6_AUTH_HASH_XOR, len);
+ if (!result)
+ return NULL;
+
+ for (i = 0; i < len; i++)
+ result[i] = mes1[i] ^ mes2[i];
+
+ return result;
+}
+
+static void md5_digest(unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+#ifdef CRYPTO_OPENSSL
+ unsigned int size = KEYCHAIN_MD5_HASH_SIZE;
+ EVP_MD_CTX *ctx;
+#elif CRYPTO_INTERNAL
+ MD5_CTX ctx;
+#endif
+
+#ifdef CRYPTO_OPENSSL
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_md5());
+ EVP_DigestUpdate(ctx, mes, len);
+ EVP_DigestFinal(ctx, digest, &size);
+ EVP_MD_CTX_free(ctx);
+#elif CRYPTO_INTERNAL
+ memset(&ctx, 0, sizeof(ctx));
+ MD5Init(&ctx);
+ MD5Update(&ctx, mes, len);
+ MD5Final(digest, &ctx);
+#endif
+}
+
+static void sha256_digest(unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+#ifdef CRYPTO_OPENSSL
+ unsigned int size = KEYCHAIN_HMAC_SHA256_HASH_SIZE;
+ EVP_MD_CTX *ctx;
+#elif CRYPTO_INTERNAL
+ SHA256_CTX ctx;
+#endif
+
+#ifdef CRYPTO_OPENSSL
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_sha256());
+ EVP_DigestUpdate(ctx, mes, len);
+ EVP_DigestFinal(ctx, digest, &size);
+ EVP_MD_CTX_free(ctx);
+#elif CRYPTO_INTERNAL
+ memset(&ctx, 0, sizeof(ctx));
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, mes, len);
+ SHA256_Final(digest, &ctx);
+#endif
+}
+
+#ifdef CRYPTO_OPENSSL
+static void sha1_digest(unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+ EVP_MD_CTX *ctx;
+ unsigned int size = KEYCHAIN_HMAC_SHA1_HASH_SIZE;
+
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_sha1());
+ EVP_DigestUpdate(ctx, mes, len);
+ EVP_DigestFinal(ctx, digest, &size);
+ EVP_MD_CTX_free(ctx);
+}
+
+static void sha384_digest(unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+ EVP_MD_CTX *ctx;
+ unsigned int size = KEYCHAIN_HMAC_SHA384_HASH_SIZE;
+
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_sha384());
+ EVP_DigestUpdate(ctx, mes, len);
+ EVP_DigestFinal(ctx, digest, &size);
+ EVP_MD_CTX_free(ctx);
+}
+
+static void sha512_digest(unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+ EVP_MD_CTX *ctx;
+ unsigned int size = KEYCHAIN_HMAC_SHA512_HASH_SIZE;
+
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_sha512());
+ EVP_DigestUpdate(ctx, mes, len);
+ EVP_DigestFinal(ctx, digest, &size);
+ EVP_MD_CTX_free(ctx);
+}
+#endif /* CRYPTO_OPENSSL */
+
+static void ospf6_hash_hmac_sha_digest(enum keychain_hash_algo key,
+ unsigned char *mes, uint32_t len,
+ unsigned char *digest)
+{
+ if ((key < KEYCHAIN_ALGO_NULL) || (key > KEYCHAIN_ALGO_MAX))
+ return;
+
+ switch (key) {
+ case KEYCHAIN_ALGO_MD5:
+ md5_digest(mes, len, digest);
+ break;
+ case KEYCHAIN_ALGO_HMAC_SHA1:
+#ifdef CRYPTO_OPENSSL
+ sha1_digest(mes, len, digest);
+#endif
+ break;
+ case KEYCHAIN_ALGO_HMAC_SHA256:
+ sha256_digest(mes, len, digest);
+ break;
+ case KEYCHAIN_ALGO_HMAC_SHA384:
+#ifdef CRYPTO_OPENSSL
+ sha384_digest(mes, len, digest);
+#endif
+ break;
+ case KEYCHAIN_ALGO_HMAC_SHA512:
+#ifdef CRYPTO_OPENSSL
+ sha512_digest(mes, len, digest);
+#endif
+ break;
+ case KEYCHAIN_ALGO_NULL:
+ case KEYCHAIN_ALGO_MAX:
+ default:
+ /* no action */
+ break;
+ }
+}
+
+uint16_t ospf6_auth_len_get(struct ospf6_interface *oi)
+{
+ uint16_t at_len = 0;
+ char *keychain_name = NULL;
+ struct keychain *keychain = NULL;
+ struct key *key = NULL;
+
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
+ if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
+ at_len = OSPF6_AUTH_HDR_MIN_SIZE
+ + keychain_get_hash_len(oi->at_data.hash_algo);
+ } else {
+ keychain_name = oi->at_data.keychain;
+ keychain = keychain_lookup(keychain_name);
+ if (keychain) {
+ key = key_lookup_for_send(keychain);
+ if (key && key->string
+ && key->hash_algo != KEYCHAIN_ALGO_NULL) {
+ at_len = OSPF6_AUTH_HDR_MIN_SIZE
+ + keychain_get_hash_len(
+ key->hash_algo);
+ }
+ }
+ }
+ } else if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ at_len = OSPF6_AUTH_HDR_MIN_SIZE
+ + keychain_get_hash_len(oi->at_data.hash_algo);
+ }
+
+ return at_len;
+}
+
+int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len,
+ struct ospf6_header *oh, unsigned int *at_len,
+ unsigned int *lls_block_len)
+{
+ struct ospf6_hello *hello = NULL;
+ struct ospf6_dbdesc *dbdesc = NULL;
+ struct ospf6_neighbor *on = NULL;
+ struct ospf6_auth_hdr ospf6_auth_info;
+ uint16_t hdr_len = 0;
+ uint32_t oh_seqnum_h = 0;
+ uint32_t oh_seqnum_l = 0;
+ bool auth_present = false;
+ bool lls_present = false;
+ struct ospf6_lls_hdr *lls_hdr = NULL;
+
+ on = ospf6_neighbor_lookup(oh->router_id, oi);
+ hdr_len = ntohs(oh->length);
+ if (*pkt_len < hdr_len) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] Received incomplete %s packet",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ } else if (*pkt_len == hdr_len) {
+ if (oi->at_data.flags != 0)
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ /* No auth info to be considered.
+ */
+ return OSPF6_AUTH_PROCESS_NORMAL;
+ }
+
+ switch (oh->type) {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ hello = (struct ospf6_hello *)((uint8_t *)oh
+ + sizeof(struct ospf6_header));
+ if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_L))
+ lls_present = true;
+
+ if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT))
+ auth_present = true;
+ break;
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh
+ + sizeof(struct ospf6_header));
+ if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_L))
+ lls_present = true;
+
+ if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT))
+ auth_present = true;
+ break;
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ if (on) {
+ lls_present = on->lls_present;
+ auth_present = on->auth_present;
+ }
+ break;
+ default:
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] : Wrong packet type %d",
+ oi->interface->name, oh->type);
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ if ((oh->type == OSPF6_MESSAGE_TYPE_HELLO)
+ || (oh->type == OSPF6_MESSAGE_TYPE_DBDESC)) {
+ if (on) {
+ on->auth_present = auth_present;
+ on->lls_present = lls_present;
+ }
+ }
+
+ if ((!auth_present && (oi->at_data.flags != 0))
+ || (auth_present && (oi->at_data.flags == 0))) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] : Auth option miss-match in %s pkt",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ if (lls_present) {
+ lls_hdr = (struct ospf6_lls_hdr *)(oh + hdr_len);
+ *lls_block_len = ntohs(lls_hdr->length) * 4;
+ }
+
+ if (*lls_block_len > (*pkt_len - hdr_len)) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] : Wrong lls data in %s packet",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ memset(&ospf6_auth_info, 0, sizeof(struct ospf6_auth_hdr));
+ if ((*pkt_len - hdr_len - (*lls_block_len)) > sizeof(ospf6_auth_info)) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] : Wrong auth data in %s packet",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ memcpy(&ospf6_auth_info, ((uint8_t *)oh + hdr_len + (*lls_block_len)),
+ (*pkt_len - hdr_len - (*lls_block_len)));
+ if (ntohs(ospf6_auth_info.length) > OSPF6_AUTH_HDR_FULL) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s] : Wrong auth header length in %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ /* after authentication header validation is done
+ * reduce the auth hdr size from the packet length
+ */
+ *at_len = ntohs(ospf6_auth_info.length);
+ *pkt_len = (*pkt_len) - (*at_len) - (*lls_block_len);
+
+ if (on) {
+ oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h);
+ oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l);
+ if ((oh_seqnum_h >= on->seqnum_h[oh->type])
+ && (oh_seqnum_l > on->seqnum_l[oh->type])) {
+ /* valid sequence number received */
+ on->seqnum_h[oh->type] = oh_seqnum_h;
+ on->seqnum_l[oh->type] = oh_seqnum_l;
+ } else {
+ if (IS_OSPF6_DEBUG_AUTH_RX) {
+ zlog_err(
+ "RECV[%s] : Nbr(%s) Auth Sequence number mismatch in %s ",
+ oi->interface->name, on->name,
+ ospf6_message_type(oh->type));
+ zlog_err(
+ "nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u",
+ on->seqnum_l[oh->type],
+ on->seqnum_h[oh->type], oh_seqnum_l,
+ oh_seqnum_h);
+ }
+
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+ }
+
+ return OSPF6_AUTH_VALIDATE_SUCCESS;
+}
+
+/* Starting point of packet process function. */
+int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
+ struct in6_addr *src, unsigned int lls_block_len)
+{
+ uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
+ unsigned char apad[hash_len];
+ unsigned char temp_hash[hash_len];
+ struct ospf6_auth_hdr *ospf6_auth;
+ uint32_t ipv6_addr_size = sizeof(struct in6_addr);
+ struct keychain *keychain = NULL;
+ struct key *key = NULL;
+ char *auth_str = NULL;
+ uint16_t auth_len = 0;
+ uint8_t hash_algo = 0;
+ uint16_t oh_len = ntohs(oh->length);
+ int ret = 0;
+
+ if (oi->at_data.flags == 0)
+ return OSPF6_AUTH_PROCESS_NORMAL;
+
+ ospf6_auth = (struct ospf6_auth_hdr *)((uint8_t *)oh +
+ (oh_len + lls_block_len));
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
+ keychain = keychain_lookup(oi->at_data.keychain);
+ if (!keychain) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err(
+ "RECV[%s]: Keychain doesn't exist for %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id));
+ if (!key) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s]: Auth, Invalid SA for %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+
+ if (key && key->string
+ && key->hash_algo != KEYCHAIN_ALGO_NULL) {
+ auth_str = key->string;
+ hash_algo = key->hash_algo;
+ } else {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err(
+ "RECV[%s]: Incomplete keychain config for %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
+ } else if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ auth_str = oi->at_data.auth_key;
+ hash_algo = oi->at_data.hash_algo;
+ }
+
+ if (!auth_str)
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+
+ hash_len = keychain_get_hash_len(hash_algo);
+ memset(apad, 0, sizeof(apad));
+ memset(temp_hash, 0, sizeof(temp_hash));
+
+ /* start digest verification */
+ memcpy(apad, src, ipv6_addr_size);
+ memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,
+ (hash_len - ipv6_addr_size));
+
+ auth_len = ntohs(ospf6_auth->length);
+
+ memcpy(temp_hash, ospf6_auth->data, hash_len);
+ memcpy(ospf6_auth->data, apad, hash_len);
+
+ ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str,
+ (oh_len + auth_len + lls_block_len),
+ hash_algo);
+
+#ifdef CRYPTO_OPENSSL
+ ret = CRYPTO_memcmp(temp_hash, ospf6_auth->data, hash_len);
+#else
+ ret = memcmp(temp_hash, ospf6_auth->data, hash_len);
+#endif
+ if (ret == 0)
+ return OSPF6_AUTH_VALIDATE_SUCCESS;
+
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+}
+
+void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
+ struct ospf6_header *oh, uint16_t auth_len,
+ uint32_t pkt_len)
+{
+ struct ospf6_auth_hdr *ospf6_auth;
+ char *keychain_name = NULL;
+ struct keychain *keychain = NULL;
+ struct key *key = NULL;
+ char *auth_str = NULL;
+ uint16_t key_id = 0;
+ enum keychain_hash_algo hash_algo = KEYCHAIN_ALGO_NULL;
+ uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;
+ unsigned char apad[hash_len];
+ int ipv6_addr_size = sizeof(struct in6_addr);
+ struct ospf6 *ospf6 = NULL;
+
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
+ if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
+ auth_str = oi->at_data.auth_key;
+ hash_algo = oi->at_data.hash_algo;
+ key_id = oi->at_data.key_id;
+ } else {
+ keychain_name = oi->at_data.keychain;
+ keychain = keychain_lookup(keychain_name);
+ if (keychain) {
+ key = key_lookup_for_send(keychain);
+ if (key && key->string
+ && key->hash_algo != KEYCHAIN_ALGO_NULL) {
+ auth_str = key->string;
+ hash_algo = key->hash_algo;
+ key_id = key->index;
+ }
+ }
+ }
+ } else if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ auth_str = oi->at_data.auth_key;
+ hash_algo = oi->at_data.hash_algo;
+ key_id = oi->at_data.key_id;
+ } else {
+ if (IS_OSPF6_DEBUG_AUTH_TX)
+ zlog_warn("SEND[%s]: Authentication not configured for %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return;
+ }
+
+ if (!auth_str) {
+ if (IS_OSPF6_DEBUG_AUTH_TX)
+ zlog_warn("SEND[%s]: Authentication key is not configured for %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ return;
+ }
+
+ hash_len = keychain_get_hash_len(hash_algo);
+ if (oi->area && oi->area->ospf6)
+ ospf6 = oi->area->ospf6;
+ else
+ return;
+
+ ospf6->seqnum_l++;
+ if (ospf6->seqnum_l == 0xFFFFFFFF) {
+ ospf6->seqnum_h++;
+ ospf6->seqnum_l = 0;
+ ospf6_auth_seqno_nvm_update(ospf6);
+ }
+
+ /* Key must be reset. which is not handled as of now. */
+ if ((ospf6->seqnum_l == 0xFFFFFFFF)
+ && (ospf6->seqnum_h == 0xFFFFFFFF)) {
+ ospf6->seqnum_l = 0;
+ ospf6->seqnum_h = 0;
+ zlog_err(
+ "Both Higher and Lower sequence number has wrapped. Need to reset the key");
+ }
+
+ memset(apad, 0, sizeof(apad));
+
+ if (src)
+ memcpy(apad, src, ipv6_addr_size);
+
+ memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,
+ (hash_len - ipv6_addr_size));
+
+ ospf6_auth =
+ (struct ospf6_auth_hdr *)((uint8_t *)oh + ntohs(oh->length));
+ ospf6_auth->type = htons(OSPF6_AUTHENTICATION_CRYPTOGRAPHIC);
+ ospf6_auth->length = htons(auth_len);
+ ospf6_auth->reserved = 0;
+ ospf6_auth->id = htons(key_id);
+ ospf6_auth->seqnum_h = htonl(ospf6->seqnum_h);
+ ospf6_auth->seqnum_l = htonl(ospf6->seqnum_l);
+ memcpy(ospf6_auth->data, apad, hash_len);
+
+ ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, pkt_len,
+ hash_algo);
+
+ /* There is a optimisation that is done to ensure that
+ * for every packet flow keychain lib API are called
+ * only once and the result are stored in oi->at_data.
+ * So, After processing the flow it is reset back here.
+ */
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {
+ oi->at_data.hash_algo = KEYCHAIN_ALGO_NULL;
+ if (oi->at_data.auth_key) {
+ XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY,
+ oi->at_data.auth_key);
+ oi->at_data.auth_key = NULL;
+ }
+
+ oi->at_data.key_id = 0;
+ UNSET_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
+ }
+}
+
+void ospf6_auth_update_digest(struct ospf6_interface *oi,
+ struct ospf6_header *oh,
+ struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
+ uint32_t pkt_len, enum keychain_hash_algo algo)
+{
+ static const uint16_t cpid = 1;
+ uint32_t hash_len = keychain_get_hash_len(algo);
+ uint32_t block_s = keychain_get_block_size(algo);
+ uint32_t k_len = strlen(auth_str);
+ uint32_t ks_len = strlen(auth_str) + sizeof(cpid);
+ unsigned char ipad[block_s];
+ unsigned char opad[block_s];
+ unsigned char ko[block_s], ks[ks_len], tmp[hash_len];
+ unsigned char *first = NULL;
+ unsigned char *second = NULL;
+ unsigned char first_mes[block_s + pkt_len];
+ unsigned char second_mes[block_s + pkt_len];
+ unsigned char first_hash[hash_len];
+ unsigned char second_hash[hash_len];
+
+ memset(ko, 0, sizeof(ko));
+ memcpy(ks, auth_str, k_len);
+ memcpy(ks + k_len, &cpid, sizeof(cpid));
+ if (ks_len > hash_len) {
+ ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp);
+ memcpy(ko, tmp, hash_len);
+ } else
+ memcpy(ko, ks, ks_len);
+
+ memcpy(ipad, ospf6_hash_ipad_max, block_s);
+ memcpy(opad, ospf6_hash_opad_max, block_s);
+
+ first = ospf6_hash_message_xor((unsigned char *)&ipad, ko, block_s);
+ second = ospf6_hash_message_xor((unsigned char *)&opad, ko, block_s);
+
+ memcpy(first_mes, first, block_s);
+ memcpy(first_mes + block_s, oh, pkt_len);
+
+ ospf6_hash_hmac_sha_digest(algo, first_mes, (block_s + pkt_len),
+ first_hash);
+
+ memcpy(second_mes, second, block_s);
+ memcpy(second_mes + block_s, first_hash, hash_len);
+
+ ospf6_hash_hmac_sha_digest(algo, second_mes, (block_s + hash_len),
+ second_hash);
+
+ memcpy(ospf6_auth->data, second_hash, hash_len);
+ XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first);
+ XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);
+}
+
+DEFUN (debug_ospf6_auth,
+ debug_ospf6_auth_cmd,
+ "debug ospf6 authentication [<tx|rx>]",
+ DEBUG_STR
+ OSPF6_STR
+ "debug OSPF6 authentication\n"
+ "debug authentication tx\n"
+ "debug authentication rx\n")
+{
+ int auth_opt_idx = 3;
+
+ if (argc == 4) {
+ if (!strncmp(argv[auth_opt_idx]->arg, "t", 1))
+ OSPF6_DEBUG_AUTH_TX_ON();
+ else if (!strncmp(argv[auth_opt_idx]->arg, "r", 1))
+ OSPF6_DEBUG_AUTH_RX_ON();
+ } else {
+ OSPF6_DEBUG_AUTH_TX_ON();
+ OSPF6_DEBUG_AUTH_RX_ON();
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf6_auth,
+ no_debug_ospf6_auth_cmd,
+ "no debug ospf6 authentication [<tx|rx>]",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "debug OSPF6 authentication\n"
+ "debug authentication tx\n"
+ "debug authentication rx\n")
+{
+ int auth_opt_idx = 3;
+
+ if (argc == 5) {
+ if (!strncmp(argv[auth_opt_idx]->arg, "t", 1))
+ OSPF6_DEBUG_AUTH_TX_OFF();
+ else if (!strncmp(argv[auth_opt_idx]->arg, "r", 1))
+ OSPF6_DEBUG_AUTH_RX_OFF();
+ } else {
+ OSPF6_DEBUG_AUTH_TX_OFF();
+ OSPF6_DEBUG_AUTH_RX_OFF();
+ }
+
+ return CMD_SUCCESS;
+}
+
+int config_write_ospf6_debug_auth(struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_AUTH_TX)
+ vty_out(vty, "debug ospf6 authentication tx\n");
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ vty_out(vty, "debug ospf6 authentication rx\n");
+ return 0;
+}
+
+void install_element_ospf6_debug_auth(void)
+{
+ install_element(ENABLE_NODE, &debug_ospf6_auth_cmd);
+ install_element(ENABLE_NODE, &no_debug_ospf6_auth_cmd);
+ install_element(CONFIG_NODE, &debug_ospf6_auth_cmd);
+ install_element(CONFIG_NODE, &no_debug_ospf6_auth_cmd);
+}
+
+/* Clear the specified interface structure */
+static void ospf6_intf_auth_clear(struct vty *vty, struct interface *ifp)
+{
+ struct ospf6_interface *oi;
+
+ if (!if_is_operative(ifp))
+ return;
+
+ if (ifp->info == NULL)
+ return;
+
+ oi = (struct ospf6_interface *)ifp->info;
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_debug(
+ "Interface %s: clear authentication rx/tx drop counters",
+ ifp->name);
+
+ /* Reset the interface rx/tx drop counters */
+ oi->at_data.tx_drop = 0;
+ oi->at_data.rx_drop = 0;
+}
+
+/* Clear interface */
+DEFUN(clear_ipv6_ospf6_intf_auth, clear_ipv6_ospf6_intf_auth_cmd,
+ "clear ipv6 ospf6 [vrf VRF] auth-counters interface [IFNAME]",
+ CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+ "authentication rx/tx drop counters\n" INTERFACE_STR IFNAME_STR)
+{
+ int idx_ifname = 0;
+ int idx_vrf = 0;
+ struct interface *ifp;
+ struct listnode *node;
+ struct ospf6 *ospf6 = NULL;
+ char *vrf_name = NULL;
+ vrf_id_t vrf_id = VRF_DEFAULT;
+ struct vrf *vrf = NULL;
+
+ if (argv_find(argv, argc, "vrf", &idx_vrf))
+ vrf_name = argv[idx_vrf + 1]->arg;
+
+ if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME))
+ vrf_name = NULL;
+
+ if (vrf_name) {
+ vrf = vrf_lookup_by_name(vrf_name);
+ if (vrf)
+ vrf_id = vrf->vrf_id;
+ }
+
+ if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
+ /* Clear all the ospfv3 interfaces auth data. */
+ for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+ if (vrf_id != ospf6->vrf_id)
+ continue;
+
+ if (!vrf)
+ vrf = vrf_lookup_by_id(ospf6->vrf_id);
+ FOR_ALL_INTERFACES (vrf, ifp)
+ ospf6_intf_auth_clear(vty, ifp);
+ }
+ } else {
+ /* Interface name is specified. */
+ ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
+ if (ifp == NULL)
+ vty_out(vty, "No such interface name\n");
+ else
+ ospf6_intf_auth_clear(vty, ifp);
+ }
+
+ return CMD_SUCCESS;
+}
+
+void install_element_ospf6_clear_intf_auth(void)
+{
+ install_element(ENABLE_NODE, &clear_ipv6_ospf6_intf_auth_cmd);
+}
+
+enum ospf6_auth_err ospf6_auth_nvm_file_exist(void)
+{
+ struct stat buffer;
+ int exist;
+
+ exist = stat(OSPF6_AUTH_SEQ_NUM_FILE, &buffer);
+ if (exist == 0)
+ return OSPF6_AUTH_FILE_EXIST;
+ else
+ return OSPF6_AUTH_FILE_DO_NOT_EXIST;
+}
+
+/*
+ * Record in non-volatile memory the given ospf6 process,
+ * authentication trailer higher order sequence number.
+ */
+void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6)
+{
+ const char *inst_name;
+ json_object *json;
+ json_object *json_instances;
+ json_object *json_instance;
+
+ zlog_err("Higher order sequence number %d update for %s process",
+ ospf6->seqnum_h, ospf6->name);
+
+ inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
+
+ json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
+ if (json == NULL)
+ json = json_object_new_object();
+
+ json_object_object_get_ex(json, "instances", &json_instances);
+ if (!json_instances) {
+ json_instances = json_object_new_object();
+ json_object_object_add(json, "instances", json_instances);
+ }
+
+ json_object_object_get_ex(json_instances, inst_name, &json_instance);
+ if (!json_instance) {
+ json_instance = json_object_new_object();
+ json_object_object_add(json_instances, inst_name,
+ json_instance);
+ }
+
+ /*
+ * Record higher order sequence number in non volatile memory.
+ */
+ json_object_int_add(json_instance, "sequence_number", ospf6->seqnum_h);
+
+ json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
+ JSON_C_TO_STRING_PRETTY);
+ json_object_free(json);
+}
+
+/*
+ * Delete authentication sequence number for a given OSPF6 process
+ * from non-volatile memory.
+ */
+void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6)
+{
+ const char *inst_name;
+ json_object *json;
+ json_object *json_instances;
+
+ zlog_err("Higher order sequence number delete for %s process",
+ ospf6->name);
+
+ inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
+
+ json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
+ if (json == NULL)
+ json = json_object_new_object();
+
+ json_object_object_get_ex(json, "instances", &json_instances);
+ if (!json_instances) {
+ json_instances = json_object_new_object();
+ json_object_object_add(json, "instances", json_instances);
+ }
+
+ json_object_object_del(json_instances, inst_name);
+
+ json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
+ JSON_C_TO_STRING_PRETTY);
+ json_object_free(json);
+}
+
+
+/*
+ * Fetch from non-volatile memory the stored ospf6 process
+ * authentication sequence number.
+ */
+void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6)
+{
+ const char *inst_name;
+ json_object *json;
+ json_object *json_instances;
+ json_object *json_instance;
+ json_object *json_seqnum;
+
+ inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME;
+
+ json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE);
+ if (json == NULL)
+ json = json_object_new_object();
+
+ json_object_object_get_ex(json, "instances", &json_instances);
+ if (!json_instances) {
+ json_instances = json_object_new_object();
+ json_object_object_add(json, "instances", json_instances);
+ }
+
+ json_object_object_get_ex(json_instances, inst_name, &json_instance);
+ if (!json_instance) {
+ json_instance = json_object_new_object();
+ json_object_object_add(json_instances, inst_name,
+ json_instance);
+ }
+
+ json_object_object_get_ex(json_instance, "sequence_number",
+ &json_seqnum);
+ ospf6->seqnum_h = json_object_get_int(json_seqnum);
+
+ zlog_err("Higher order sequence number %d read for %s process %s",
+ ospf6->seqnum_h, ospf6->name, strerror(errno));
+
+ json_object_object_del(json_instances, inst_name);
+ json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json,
+ JSON_C_TO_STRING_PRETTY);
+ json_object_free(json);
+}
diff --git a/ospf6d/ospf6_auth_trailer.h b/ospf6d/ospf6_auth_trailer.h
new file mode 100644
index 0000000000..dea4a6e168
--- /dev/null
+++ b/ospf6d/ospf6_auth_trailer.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 Abhinay Ramesh
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra 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.
+ *
+ * GNU Zebra 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 __OSPF6_AUTH_TRAILER_H__
+#define __OSPF6_AUTH_TRAILER_H__
+
+#include "lib/keychain.h"
+#include "ospf6_message.h"
+
+#define OSPF6_AUTH_HDR_MIN_SIZE 16
+#define OSPF6_AUTH_HDR_FULL KEYCHAIN_MAX_HASH_SIZE + OSPF6_AUTH_HDR_MIN_SIZE
+
+#define OSPF6_AUTHENTICATION_NULL 0
+#define OSPF6_AUTHENTICATION_CRYPTOGRAPHIC 1
+
+/* Auth debug options */
+extern unsigned char conf_debug_ospf6_auth[2];
+
+#define OSPF6_AUTH_TX 0
+#define OSPF6_AUTH_RX 1
+#define OSPF6_DEBUG_AUTH_TX_ON() (conf_debug_ospf6_auth[OSPF6_AUTH_TX] = 1)
+#define OSPF6_DEBUG_AUTH_TX_OFF() (conf_debug_ospf6_auth[OSPF6_AUTH_TX] = 0)
+#define OSPF6_DEBUG_AUTH_RX_ON() (conf_debug_ospf6_auth[OSPF6_AUTH_RX] = 1)
+#define OSPF6_DEBUG_AUTH_RX_OFF() (conf_debug_ospf6_auth[OSPF6_AUTH_RX] = 0)
+#define IS_OSPF6_DEBUG_AUTH_TX (conf_debug_ospf6_auth[OSPF6_AUTH_TX])
+#define IS_OSPF6_DEBUG_AUTH_RX (conf_debug_ospf6_auth[OSPF6_AUTH_RX])
+
+#define OSPF6_AUTH_TRAILER_KEYCHAIN (1 << 0)
+#define OSPF6_AUTH_TRAILER_MANUAL_KEY (1 << 1)
+#define OSPF6_AUTH_TRAILER_KEYCHAIN_VALID (1 << 2)
+
+/* According to sesion 4.1 of RFC7166 defining the trailer struct */
+struct ospf6_auth_hdr {
+ uint16_t type;
+ uint16_t length;
+ uint16_t reserved;
+ uint16_t id;
+ uint32_t seqnum_h;
+ uint32_t seqnum_l;
+ unsigned char data[KEYCHAIN_MAX_HASH_SIZE];
+};
+
+enum ospf6_auth_err {
+ OSPF6_AUTH_VALIDATE_SUCCESS = 0,
+ OSPF6_AUTH_VALIDATE_FAILURE,
+ OSPF6_AUTH_PROCESS_NORMAL,
+ OSPF6_AUTH_FILE_EXIST,
+ OSPF6_AUTH_FILE_DO_NOT_EXIST
+};
+
+void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length);
+void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length,
+ unsigned int lls_len);
+unsigned char *ospf6_hash_message_xor(unsigned char *mes1, unsigned char *mes2,
+ uint32_t len);
+uint16_t ospf6_auth_len_get(struct ospf6_interface *oi);
+int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len,
+ struct ospf6_header *oh, unsigned int *at_len,
+ unsigned int *lls_block_len);
+int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
+ struct in6_addr *src, unsigned int lls_len);
+void ospf6_auth_update_digest(struct ospf6_interface *oi,
+ struct ospf6_header *oh,
+ struct ospf6_auth_hdr *ospf6_auth, char *auth_str,
+ uint32_t pkt_len, enum keychain_hash_algo algo);
+void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,
+ struct ospf6_header *oh, uint16_t auth_len,
+ uint32_t pkt_len);
+void install_element_ospf6_debug_auth(void);
+int config_write_ospf6_debug_auth(struct vty *vty);
+void install_element_ospf6_clear_intf_auth(void);
+enum ospf6_auth_err ospf6_auth_nvm_file_exist(void);
+void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6);
+void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6);
+void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6);
+#endif /* __OSPF6_AUTH_TRAILER_H__ */
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 0d9f15d08f..f39d208bb5 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -46,8 +46,13 @@
#include "ospf6_zebra.h"
#include "ospf6_gr.h"
#include "lib/json.h"
+#include "ospf6_proto.h"
+#include "lib/keychain.h"
+#include "ospf6_auth_trailer.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
+DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_KEYCHAIN, "OSPF6 auth keychain");
+DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_MANUAL_KEY, "OSPF6 auth key");
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
DEFINE_QOBJ_TYPE(ospf6_interface);
DEFINE_HOOK(ospf6_interface_change,
@@ -252,6 +257,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
/* Compute cost. */
oi->cost = ospf6_interface_get_cost(oi);
+ oi->at_data.flags = 0;
+
return oi;
}
@@ -990,6 +997,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
struct ospf6_lsa *lsa, *lsanext;
json_object *json_arr;
json_object *json_addr;
+ struct json_object *json_auth = NULL;
default_iftype = ospf6_default_iftype(ifp);
@@ -1238,6 +1246,48 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
}
}
+ json_auth = json_object_new_object();
+ if (oi->at_data.flags != 0) {
+ if (use_json) {
+ if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN)) {
+ json_object_string_add(json_auth, "authType",
+ "keychain");
+ json_object_string_add(json_auth,
+ "keychainName",
+ oi->at_data.keychain);
+ } else if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_MANUAL_KEY))
+ json_object_string_add(json_auth, "authType",
+ "manualkey");
+ json_object_int_add(json_auth, "txPktDrop",
+ oi->at_data.tx_drop);
+ json_object_int_add(json_auth, "rxPktDrop",
+ oi->at_data.rx_drop);
+ } else {
+ if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN))
+ vty_out(vty,
+ " Authentication Trailer is enabled with key-chain %s\n",
+ oi->at_data.keychain);
+ else if (CHECK_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_MANUAL_KEY))
+ vty_out(vty,
+ " Authentication trailer is enabled with manual key\n");
+ vty_out(vty,
+ " Packet drop Tx %u, Packet drop Rx %u\n",
+ oi->at_data.tx_drop, oi->at_data.rx_drop);
+ }
+ } else {
+ if (use_json)
+ json_object_string_add(json_auth, "authType", "NULL");
+ else
+ vty_out(vty, " Authentication Trailer is disabled\n");
+ }
+
+ if (use_json)
+ json_object_object_add(json_obj, "authInfo", json_auth);
+
return 0;
}
@@ -2577,6 +2627,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
ospf6_bfd_write_config(vty, oi);
+ ospf6_auth_write_config(vty, &oi->at_data);
if_vty_config_end(vty);
}
return 0;
@@ -2815,3 +2866,195 @@ void install_element_ospf6_debug_interface(void)
install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
}
+
+void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
+{
+ if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
+ vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",
+ at_data->keychain);
+ else if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
+ vty_out(vty,
+ " ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",
+ at_data->key_id,
+ keychain_get_algo_name_by_id(at_data->hash_algo),
+ at_data->auth_key);
+}
+
+DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
+ ipv6_ospf6_intf_auth_trailer_keychain_cmd,
+ "ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
+ IP6_STR OSPF6_STR
+ "Enable authentication on this interface\n"
+ "Keychain\n"
+ "Keychain name\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ int keychain_idx = 4;
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+
+ assert(oi);
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ vty_out(vty,
+ "Manual key configured, unconfigure it before configuring key chain\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);
+ if (oi->at_data.keychain)
+ XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
+
+ oi->at_data.keychain =
+ XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
+ no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
+ "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
+ NO_STR IP6_STR OSPF6_STR
+ "Enable authentication on this interface\n"
+ "Keychain\n"
+ "Keychain name\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+
+ assert(oi);
+ if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
+ return CMD_SUCCESS;
+
+ if (oi->at_data.keychain) {
+ oi->at_data.flags = 0;
+ XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
+ oi->at_data.keychain = NULL;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
+ "ipv6 ospf6 authentication key-id (1-65535) hash-algo "
+ "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
+ "key WORD",
+ IP6_STR OSPF6_STR
+ "Authentication\n"
+ "Key ID\n"
+ "Key ID value\n"
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n"
+ "Password\n"
+ "Password string (key)\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ int key_id_idx = 4;
+ int hash_algo_idx = 6;
+ int password_idx = 8;
+ struct ospf6_interface *oi;
+ uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
+
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+
+ assert(oi);
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
+ vty_out(vty,
+ "key chain configured, unconfigure it before configuring manual key\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
+#ifndef CRYPTO_OPENSSL
+ if (hash_algo == KEYCHAIN_ALGO_NULL) {
+ vty_out(vty,
+ "Hash algorithm not supported, compile with --with-crypto=openssl\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+#endif /* CRYPTO_OPENSSL */
+
+ SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY);
+ oi->at_data.hash_algo = hash_algo;
+ oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10);
+ if (oi->at_data.auth_key)
+ XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
+ oi->at_data.auth_key =
+ XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
+ no_ipv6_ospf6_intf_auth_trailer_key_cmd,
+ "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
+ "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
+ "key WORD]",
+ NO_STR IP6_STR OSPF6_STR
+ "Authentication\n"
+ "Key ID\n"
+ "Key ID value\n"
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n"
+ "Password\n"
+ "Password string (key)\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf6_interface *oi;
+#ifndef CRYPTO_OPENSSL
+ int hash_algo_idx = 7;
+ uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
+#endif /* CRYPTO_OPENSSL */
+
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create(ifp);
+
+ assert(oi);
+ if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
+ return CMD_SUCCESS;
+
+#ifndef CRYPTO_OPENSSL
+ hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
+ if (hash_algo == KEYCHAIN_ALGO_NULL) {
+ vty_out(vty,
+ "Hash algorithm not supported, compile with --with-crypto=openssl\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+#endif /* CRYPTO_OPENSSL */
+
+ if (oi->at_data.auth_key) {
+ oi->at_data.flags = 0;
+ XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
+ oi->at_data.auth_key = NULL;
+ }
+
+ return CMD_SUCCESS;
+}
+
+void ospf6_interface_auth_trailer_cmd_init(void)
+{
+ /*Install OSPF6 auth trailer commands at interface level */
+ install_element(INTERFACE_NODE,
+ &ipv6_ospf6_intf_auth_trailer_keychain_cmd);
+ install_element(INTERFACE_NODE,
+ &no_ipv6_ospf6_intf_auth_trailer_keychain_cmd);
+ install_element(INTERFACE_NODE, &ipv6_ospf6_intf_auth_trailer_key_cmd);
+ install_element(INTERFACE_NODE,
+ &no_ipv6_ospf6_intf_auth_trailer_key_cmd);
+}
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index ee24b989bd..59e4888a5f 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -24,6 +24,9 @@
#include "qobj.h"
#include "hook.h"
#include "if.h"
+#include "ospf6d.h"
+
+DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);
/* Debug option */
extern unsigned char conf_debug_ospf6_interface;
@@ -31,6 +34,21 @@ extern unsigned char conf_debug_ospf6_interface;
#define OSPF6_DEBUG_INTERFACE_OFF() (conf_debug_ospf6_interface = 0)
#define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface)
+struct ospf6_auth_data {
+ /* config data */
+ uint8_t hash_algo; /* hash algorithm type */
+ uint16_t key_id; /* key-id used as SA in auth packet */
+ char *auth_key; /* Auth key */
+ char *keychain; /* keychain name */
+
+ /* operational data */
+ uint8_t flags; /* Flags related to auth config */
+
+ /* Counters and Statistics */
+ uint32_t tx_drop; /* Pkt drop due to auth fail while sending */
+ uint32_t rx_drop; /* Pkt drop due to auth fail while reading */
+};
+
/* Interface structure */
struct ospf6_interface {
/* IF info from zebra */
@@ -95,6 +113,9 @@ struct ospf6_interface {
/* MTU mismatch check */
uint8_t mtu_ignore;
+ /* Authentication trailer related config */
+ struct ospf6_auth_data at_data;
+
/* Decision of DR Election */
in_addr_t drouter;
in_addr_t bdrouter;
@@ -221,6 +242,9 @@ extern void install_element_ospf6_debug_interface(void);
extern int ospf6_interface_neighbor_count(struct ospf6_interface *oi);
extern uint8_t dr_election(struct ospf6_interface *oi);
+extern void ospf6_interface_auth_trailer_cmd_init(void);
+extern void ospf6_auth_write_config(struct vty *vty,
+ struct ospf6_auth_data *at_data);
DECLARE_HOOK(ospf6_interface_change,
(struct ospf6_interface * oi, int state, int old_state),
(oi, state, old_state));
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 6626b4bed5..da5cad0537 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -2148,7 +2148,7 @@ static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
char installed[64], changed[64];
struct timeval now, res;
char id[16], adv_router[16];
- char capa[16], options[16];
+ char capa[16], options[32];
brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 165a764c38..120f307adc 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -20,6 +20,7 @@
#include <zebra.h>
#include <lib/version.h>
+#include <lib/keychain.h>
#include <stdlib.h>
#include "getopt.h"
@@ -223,6 +224,7 @@ int main(int argc, char *argv[], char *envp[])
/* thread master */
master = om6->master;
+ keychain_init();
ospf6_vrf_init();
access_list_init();
prefix_list_init();
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 352cb137ed..7ebfdd26e1 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -27,6 +27,7 @@
#include "thread.h"
#include "linklist.h"
#include "lib_errors.h"
+#include "checksum.h"
#include "ospf6_proto.h"
#include "ospf6_lsa.h"
@@ -48,19 +49,34 @@
#include "ospf6d.h"
#include "ospf6_gr.h"
#include <netinet/ip6.h>
+#include "lib/libospf.h"
+#include "lib/keychain.h"
+#include "ospf6_auth_trailer.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
-static const struct message ospf6_message_type_str[] = {
- {OSPF6_MESSAGE_TYPE_HELLO, "Hello"},
- {OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc"},
- {OSPF6_MESSAGE_TYPE_LSREQ, "LSReq"},
- {OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate"},
- {OSPF6_MESSAGE_TYPE_LSACK, "LSAck"},
- {0}};
+
+const char *ospf6_message_type(int type)
+{
+ switch (type) {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ return "Hello";
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ return "DbDesc";
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ return "LSReq";
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ return "LSUpdate";
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ return "LSAck";
+ case OSPF6_MESSAGE_TYPE_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
/* Minimum (besides the standard OSPF packet header) lengths for OSPF
packets of particular types, offset is the "type" field. */
@@ -101,7 +117,7 @@ static void ospf6_header_print(struct ospf6_header *oh)
void ospf6_hello_print(struct ospf6_header *oh, int action)
{
struct ospf6_hello *hello;
- char options[16];
+ char options[32];
char *p;
ospf6_header_print(oh);
@@ -136,7 +152,7 @@ void ospf6_hello_print(struct ospf6_header *oh, int action)
void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
{
struct ospf6_dbdesc *dbdesc;
- char options[16];
+ char options[32];
char *p;
ospf6_header_print(oh);
@@ -439,6 +455,20 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
return;
}
+ if (((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) ==
+ OSPF6_OPT_AT) &&
+ (oi->at_data.flags == 0)) ||
+ ((OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT) !=
+ OSPF6_OPT_AT) &&
+ (oi->at_data.flags != 0))) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_warn(
+ "VRF %s: IF %s AT-bit mismatch in hello packet",
+ oi->interface->vrf->name, oi->interface->name);
+ oi->at_data.rx_drop++;
+ return;
+ }
+
/* Find neighbor, create if not exist */
on = ospf6_neighbor_lookup(oh->router_id, oi);
if (on == NULL) {
@@ -1006,6 +1036,20 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh
+ sizeof(struct ospf6_header));
+ if (((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) ==
+ OSPF6_OPT_AT) &&
+ (oi->at_data.flags == 0)) ||
+ ((OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT) !=
+ OSPF6_OPT_AT) &&
+ (oi->at_data.flags != 0))) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_warn(
+ "VRF %s: IF %s AT-bit mismatch in dbdesc packet",
+ oi->interface->vrf->name, oi->interface->name);
+ oi->at_data.rx_drop++;
+ return;
+ }
+
/* Interface MTU check */
if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) {
zlog_warn("VRF %s: I/F %s MTU mismatch (my %d rcvd %d)",
@@ -1412,14 +1456,15 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
bytesonwire);
return MSG_NG;
}
+
/* Now it is safe to access header fields. */
if (bytesonwire != ntohs(oh->length)) {
zlog_warn("%s: %s packet length error (%u real, %u declared)",
- __func__,
- lookup_msg(ospf6_message_type_str, oh->type, NULL),
- bytesonwire, ntohs(oh->length));
+ __func__, ospf6_message_type(oh->type), bytesonwire,
+ ntohs(oh->length));
return MSG_NG;
}
+
/* version check */
if (oh->version != OSPFV3_VERSION) {
zlog_warn("%s: invalid (%u) protocol version", __func__,
@@ -1431,8 +1476,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
&& bytesonwire
< OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
zlog_warn("%s: undersized (%u B) %s packet", __func__,
- bytesonwire,
- lookup_msg(ospf6_message_type_str, oh->type, NULL));
+ bytesonwire, ospf6_message_type(oh->type));
return MSG_NG;
}
/* type-specific deeper validation */
@@ -1446,7 +1490,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
% 4)
return MSG_OK;
zlog_warn("%s: alignment error in %s packet", __func__,
- lookup_msg(ospf6_message_type_str, oh->type, NULL));
+ ospf6_message_type(oh->type));
return MSG_NG;
case OSPF6_MESSAGE_TYPE_DBDESC:
/* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes
@@ -1467,7 +1511,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
% OSPF6_LSREQ_LSDESC_FIX_SIZE)
return MSG_OK;
zlog_warn("%s: alignment error in %s packet", __func__,
- lookup_msg(ospf6_message_type_str, oh->type, NULL));
+ ospf6_message_type(oh->type));
return MSG_NG;
case OSPF6_MESSAGE_TYPE_LSUPDATE:
/* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes
@@ -1497,7 +1541,7 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
}
if (test != MSG_OK)
zlog_warn("%s: anomaly in %s packet", __func__,
- lookup_msg(ospf6_message_type_str, oh->type, NULL));
+ ospf6_message_type(oh->type));
return test;
}
@@ -1727,6 +1771,9 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
struct iovec iovector[2];
struct ospf6_interface *oi;
struct ospf6_header *oh;
+ enum ospf6_auth_err ret = OSPF6_AUTH_PROCESS_NORMAL;
+ uint32_t at_len = 0;
+ uint32_t lls_len = 0;
/* initialize */
memset(&src, 0, sizeof(src));
@@ -1772,6 +1819,24 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
return OSPF6_READ_CONTINUE;
oh = (struct ospf6_header *)recvbuf;
+ ret = ospf6_auth_validate_pkt(oi, (uint32_t *)&len, oh, &at_len,
+ &lls_len);
+ if (ret == OSPF6_AUTH_VALIDATE_SUCCESS) {
+ ret = ospf6_auth_check_digest(oh, oi, &src, lls_len);
+ if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err(
+ "RECV[%s]: OSPF packet auth digest miss-match on %s",
+ oi->interface->name,
+ ospf6_message_type(oh->type));
+ oi->at_data.rx_drop++;
+ return OSPF6_READ_CONTINUE;
+ }
+ } else if (ret == OSPF6_AUTH_VALIDATE_FAILURE) {
+ oi->at_data.rx_drop++;
+ return OSPF6_READ_CONTINUE;
+ }
+
if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK)
return OSPF6_READ_CONTINUE;
@@ -1782,8 +1847,7 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
/* Log */
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
- zlog_debug("%s received on %s",
- lookup_msg(ospf6_message_type_str, oh->type, NULL),
+ zlog_debug("%s received on %s", ospf6_message_type(oh->type),
oi->interface->name);
zlog_debug(" src: %pI6", &src);
zlog_debug(" dst: %pI6", &dst);
@@ -1807,6 +1871,10 @@ static int ospf6_read_helper(int sockfd, struct ospf6 *ospf6)
default:
assert(0);
}
+
+ if ((at_len != 0) && IS_OSPF6_DEBUG_AUTH_RX)
+ ospf6_auth_hdr_dump_recv(oh, (len + at_len + lls_len),
+ lls_len);
}
switch (oh->type) {
@@ -1863,6 +1931,27 @@ int ospf6_receive(struct thread *thread)
return 0;
}
+static void ospf6_fill_hdr_checksum(struct ospf6_interface *oi,
+ struct ospf6_packet *op)
+{
+ struct ipv6_ph ph = {};
+ struct ospf6_header *oh;
+ void *offset = NULL;
+
+ if (oi->at_data.flags != 0)
+ return;
+
+ memcpy(&ph.src, oi->linklocal_addr, sizeof(struct in6_addr));
+ memcpy(&ph.dst, &op->dst, sizeof(struct in6_addr));
+ ph.ulpl = htonl(op->length);
+ ph.next_hdr = IPPROTO_OSPFIGP;
+
+ /* Suppress static analysis warnings about accessing icmp6 oob */
+ oh = (struct ospf6_header *)STREAM_DATA(op->s);
+ offset = oh;
+ oh->checksum = in_cksum_with_ph6(&ph, offset, op->length);
+}
+
static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
struct stream *s)
{
@@ -1873,6 +1962,7 @@ static void ospf6_make_header(uint8_t type, struct ospf6_interface *oi,
oh->version = (uint8_t)OSPFV3_VERSION;
oh->type = type;
oh->length = 0;
+
oh->router_id = oi->area->ospf6->router_id;
oh->area_id = oi->area->area_id;
oh->checksum = 0;
@@ -1904,9 +1994,48 @@ static void ospf6_fill_lsupdate_header(struct stream *s, uint32_t lsa_num)
lsu->lsa_number = htonl(lsa_num);
}
-static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
+static void ospf6_auth_trailer_copy_keychain_key(struct ospf6_interface *oi)
+{
+ char *keychain_name = NULL;
+ struct keychain *keychain = NULL;
+ struct key *key = NULL;
+
+ keychain_name = oi->at_data.keychain;
+ keychain = keychain_lookup(keychain_name);
+ if (keychain) {
+ key = key_lookup_for_send(keychain);
+ if (key && key->string &&
+ key->hash_algo != KEYCHAIN_ALGO_NULL) {
+ /* storing the values so that further
+ * lookup can be avoided. after
+ * processing the digest need to reset
+ * these values
+ */
+ oi->at_data.hash_algo = key->hash_algo;
+ oi->at_data.auth_key = XSTRDUP(
+ MTYPE_OSPF6_AUTH_MANUAL_KEY, key->string);
+ oi->at_data.key_id = key->index;
+ SET_FLAG(oi->at_data.flags,
+ OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);
+ }
+ }
+}
+
+static uint16_t ospf6_packet_max(struct ospf6_interface *oi)
{
+ uint16_t at_len = 0;
+
assert(oi->ifmtu > sizeof(struct ip6_hdr));
+
+ if (oi->at_data.flags != 0) {
+ if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
+ ospf6_auth_trailer_copy_keychain_key(oi);
+
+ at_len += OSPF6_AUTH_HDR_MIN_SIZE;
+ at_len += keychain_get_hash_len(oi->at_data.hash_algo);
+ return oi->ifmtu - (sizeof(struct ip6_hdr)) - at_len;
+ }
+
return oi->ifmtu - (sizeof(struct ip6_hdr));
}
@@ -1915,11 +2044,15 @@ static uint16_t ospf6_make_hello(struct ospf6_interface *oi, struct stream *s)
struct listnode *node, *nnode;
struct ospf6_neighbor *on;
uint16_t length = OSPF6_HELLO_MIN_SIZE;
+ uint8_t options1 = oi->area->options[1];
+
+ if (oi->at_data.flags != 0)
+ options1 |= OSPF6_OPT_AT;
stream_putl(s, oi->interface->ifindex);
stream_putc(s, oi->priority);
stream_putc(s, oi->area->options[0]);
- stream_putc(s, oi->area->options[1]);
+ stream_putc(s, options1);
stream_putc(s, oi->area->options[2]);
stream_putw(s, oi->hello_interval);
stream_putw(s, oi->dead_interval);
@@ -1959,6 +2092,7 @@ static int ospf6_write(struct thread *thread)
int len;
int64_t latency = 0;
struct timeval timestamp;
+ uint16_t at_len = 0;
if (ospf6->fd < 0) {
zlog_warn("ospf6_write failed to send, fd %d", ospf6->fd);
@@ -1983,17 +2117,32 @@ static int ospf6_write(struct thread *thread)
oh = (struct ospf6_header *)STREAM_DATA(op->s);
+ if (oi->at_data.flags != 0) {
+ at_len = ospf6_auth_len_get(oi);
+ if (at_len) {
+ iovector[0].iov_len =
+ ntohs(oh->length) + at_len;
+ ospf6_auth_digest_send(oi->linklocal_addr, oi,
+ oh, at_len,
+ iovector[0].iov_len);
+ } else {
+ iovector[0].iov_len = ntohs(oh->length);
+ }
+ } else {
+ iovector[0].iov_len = ntohs(oh->length);
+ }
+
len = ospf6_sendmsg(oi->linklocal_addr, &op->dst,
oi->interface->ifindex, iovector,
ospf6->fd);
- if (len != op->length)
+
+ if (len != (op->length + (int)at_len))
flog_err(EC_LIB_DEVELOPMENT,
"Could not send entire message");
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
zlog_debug("%s send on %s",
- lookup_msg(ospf6_message_type_str, oh->type,
- NULL),
+ ospf6_message_type(oh->type),
oi->interface->name);
zlog_debug(" src: %pI6", oi->linklocal_addr);
zlog_debug(" dst: %pI6", &op->dst);
@@ -2052,6 +2201,15 @@ static int ospf6_write(struct thread *thread)
assert(0);
break;
}
+
+ if ((oi->at_data.flags != 0) &&
+ (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) &&
+ (IS_OSPF6_DEBUG_AUTH_TX))
+ ospf6_auth_hdr_dump_send(oh, iovector[0].iov_len);
+
+ /* initialize at_len to 0 for next packet */
+ at_len = 0;
+
/* Now delete packet from queue. */
ospf6_packet_delete(oi);
@@ -2117,6 +2275,8 @@ int ospf6_hello_send(struct thread *thread)
op->dst = allspfrouters6;
+ ospf6_fill_hdr_checksum(oi, op);
+
/* Add packet to the top of the interface output queue, so that they
* can't get delayed by things like long queues of LS Update packets
*/
@@ -2135,6 +2295,10 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
{
uint16_t length = OSPF6_DB_DESC_MIN_SIZE;
struct ospf6_lsa *lsa, *lsanext;
+ uint8_t options1 = on->ospf6_if->area->options[1];
+
+ if (on->ospf6_if->at_data.flags != 0)
+ options1 |= OSPF6_OPT_AT;
/* if this is initial one, initialize sequence number for DbDesc */
if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
@@ -2145,7 +2309,7 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
/* reserved */
stream_putc(s, 0); /* reserved 1 */
stream_putc(s, on->ospf6_if->area->options[0]);
- stream_putc(s, on->ospf6_if->area->options[1]);
+ stream_putc(s, options1);
stream_putc(s, on->ospf6_if->area->options[2]);
stream_putw(s, on->ospf6_if->ifmtu);
stream_putc(s, 0); /* reserved 2 */
@@ -2212,6 +2376,8 @@ int ospf6_dbdesc_send(struct thread *thread)
else
op->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, op);
+
ospf6_packet_add(on->ospf6_if, op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
@@ -2319,6 +2485,7 @@ static uint16_t ospf6_make_lsack_neighbor(struct ospf6_neighbor *on,
(*op)->length = length + OSPF6_HEADER_SIZE;
(*op)->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, *op);
ospf6_packet_add(on->ospf6_if, *op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
/* new packet */
@@ -2388,6 +2555,7 @@ int ospf6_lsreq_send(struct thread *thread)
else
op->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, op);
ospf6_packet_add(on->ospf6_if, op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
@@ -2425,6 +2593,7 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
op->dst = alldrouters6;
}
if (oi) {
+ ospf6_fill_hdr_checksum(oi, op);
ospf6_packet_add(oi, op);
/* If ospf instance is being deleted, send the packet
* immediately
@@ -2452,9 +2621,8 @@ static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
- if ((length + (unsigned int)OSPF6_LSA_SIZE(lsa->header)
- + OSPF6_HEADER_SIZE)
- > ospf6_packet_max(on->ospf6_if)) {
+ if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
+ ospf6_packet_max(on->ospf6_if)) {
ospf6_fill_header(on->ospf6_if, (*op)->s,
length + OSPF6_HEADER_SIZE);
(*op)->length = length + OSPF6_HEADER_SIZE;
@@ -2490,9 +2658,8 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
- if ((length + (unsigned int)OSPF6_LSA_SIZE(lsa->header)
- + OSPF6_HEADER_SIZE)
- > ospf6_packet_max(on->ospf6_if)) {
+ if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
+ ospf6_packet_max(on->ospf6_if)) {
ospf6_fill_header(on->ospf6_if, (*op)->s,
length + OSPF6_HEADER_SIZE);
(*op)->length = length + OSPF6_HEADER_SIZE;
@@ -2502,6 +2669,7 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
else
(*op)->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, *op);
ospf6_packet_add(on->ospf6_if, *op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
@@ -2573,6 +2741,7 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
op->dst = allspfrouters6;
else
op->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, op);
ospf6_packet_add(on->ospf6_if, op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
} else
@@ -2629,9 +2798,8 @@ static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface *oi,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
- if (length + (unsigned int)OSPF6_LSA_SIZE(lsa->header)
- + OSPF6_HEADER_SIZE
- > ospf6_packet_max(oi)) {
+ if (length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE >
+ ospf6_packet_max(oi)) {
ospf6_fill_header(oi, (*op)->s,
length + OSPF6_HEADER_SIZE);
(*op)->length = length + OSPF6_HEADER_SIZE;
@@ -2739,6 +2907,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
/* Set packet length, dst and queue to FIFO. */
op->length = length;
op->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(on->ospf6_if, op);
ospf6_packet_add(on->ospf6_if, op);
OSPF6_MESSAGE_WRITE_ON(on->ospf6_if);
@@ -2823,6 +2992,7 @@ int ospf6_lsack_send_interface(struct thread *thread)
else
op->dst = alldrouters6;
+ ospf6_fill_hdr_checksum(oi, op);
ospf6_packet_add(oi, op);
OSPF6_MESSAGE_WRITE_ON(oi);
diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h
index 0cd10ef825..437dd5685b 100644
--- a/ospf6d/ospf6_message.h
+++ b/ospf6d/ospf6_message.h
@@ -25,6 +25,7 @@
/* Debug option */
extern unsigned char conf_debug_ospf6_message[];
+
#define OSPF6_ACTION_SEND 0x01
#define OSPF6_ACTION_RECV 0x02
#define OSPF6_DEBUG_MESSAGE_SEND 0x01
@@ -62,6 +63,7 @@ extern unsigned char conf_debug_ospf6_message[];
#define OSPF6_MESSAGE_TYPE_LSUPDATE 0x4 /* Database update */
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
+#define OSPF6_MESSAGE_TYPE_MAX 0x6 /* same as OSPF6_MESSAGE_TYPE_ALL */
struct ospf6_packet {
struct ospf6_packet *next;
@@ -146,8 +148,16 @@ struct ospf6_lsupdate {
/* Followed by LSAs */
};
+/* LLS is not supported, but used to derive
+ * offset of Auth_trailer
+ */
+struct ospf6_lls_hdr {
+ uint16_t checksum;
+ uint16_t length;
+};
+
/* Link State Acknowledgement */
-#define OSPF6_LS_ACK_MIN_SIZE 0U
+#define OSPF6_LS_ACK_MIN_SIZE 0U
/* It is just a sequence of LSA Headers */
/* Function definition */
@@ -176,5 +186,5 @@ extern int ospf6_lsack_send_neighbor(struct thread *thread);
extern int config_write_ospf6_debug_message(struct vty *);
extern void install_element_ospf6_debug_message(void);
-
+extern const char *ospf6_message_type(int type);
#endif /* OSPF6_MESSAGE_H */
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index afa504d13c..5d14bfc981 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -112,6 +112,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
{
struct ospf6_neighbor *on;
char buf[16];
+ int type;
on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
@@ -131,6 +132,13 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
on->lsupdate_list = ospf6_lsdb_create(on);
on->lsack_list = ospf6_lsdb_create(on);
+ for (type = 0; type < OSPF6_MESSAGE_TYPE_MAX; type++) {
+ on->seqnum_l[type] = 0;
+ on->seqnum_h[type] = 0;
+ }
+
+ on->auth_present = false;
+
listnode_add_sort(oi->neighbor_list, on);
ospf6_bfd_info_nbr_create(oi, on);
@@ -935,8 +943,44 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
bfd_sess_show(vty, json_neighbor, on->bfd_session);
- json_object_object_add(json, on->name, json_neighbor);
+ if (on->auth_present == true) {
+ json_object_string_add(json_neighbor, "authStatus",
+ "enabled");
+ json_object_int_add(
+ json_neighbor, "recvdHelloHigherSeqNo",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO]);
+ json_object_int_add(
+ json_neighbor, "recvdHelloLowerSeqNo",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO]);
+ json_object_int_add(
+ json_neighbor, "recvdDBDescHigherSeqNo",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC]);
+ json_object_int_add(
+ json_neighbor, "recvdDBDescLowerSeqNo",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC]);
+ json_object_int_add(
+ json_neighbor, "recvdLSReqHigherSeqNo",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ]);
+ json_object_int_add(
+ json_neighbor, "recvdLSReqLowerSeqNo",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ]);
+ json_object_int_add(
+ json_neighbor, "recvdLSUpdHigherSeqNo",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE]);
+ json_object_int_add(
+ json_neighbor, "recvdLSUpdLowerSeqNo",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE]);
+ json_object_int_add(
+ json_neighbor, "recvdLSAckHigherSeqNo",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]);
+ json_object_int_add(
+ json_neighbor, "recvdLSAckLowerSeqNo",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]);
+ } else
+ json_object_string_add(json_neighbor, "authStatus",
+ "disabled");
+ json_object_object_add(json, on->name, json_neighbor);
} else {
vty_out(vty, " Neighbor %s\n", on->name);
@@ -1022,6 +1066,27 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
vty_out(vty, " %s\n", lsa->name);
bfd_sess_show(vty, NULL, on->bfd_session);
+
+ if (on->auth_present == true) {
+ vty_out(vty, " Authentication header present\n");
+ vty_out(vty,
+ "\t\t\t hello DBDesc LSReq LSUpd LSAck\n");
+ vty_out(vty,
+ " Higher sequence no 0x%-10X 0x%-10X 0x%-10X 0x%-10X 0x%-10X\n",
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO],
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC],
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ],
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE],
+ on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]);
+ vty_out(vty,
+ " Lower sequence no 0x%-10X 0x%-10X 0x%-10X 0x%-10X 0x%-10X\n",
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO],
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC],
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ],
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE],
+ on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]);
+ } else
+ vty_out(vty, " Authentication header not present\n");
}
}
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index de59a1ccf5..2dd640099c 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -144,6 +144,14 @@ struct ospf6_neighbor {
/* ospf6 graceful restart HELPER info */
struct ospf6_helper_info gr_helper_info;
+
+ /* seqnum_h/l is used to compare sequence
+ * number in received packet Auth header
+ */
+ uint32_t seqnum_h[OSPF6_MESSAGE_TYPE_MAX];
+ uint32_t seqnum_l[OSPF6_MESSAGE_TYPE_MAX];
+ bool auth_present;
+ bool lls_present;
};
/* Neighbor state */
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index 5961cfe66a..7501f49fe0 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -33,6 +33,7 @@
#include "ospf6_top.h"
#include "ospf6_network.h"
#include "ospf6d.h"
+#include "ospf6_message.h"
struct in6_addr allspfrouters6;
struct in6_addr alldrouters6;
@@ -60,20 +61,6 @@ static void ospf6_set_transport_class(int ospf6_sock)
#endif
}
-static void ospf6_set_checksum(int ospf6_sock)
-{
- int offset = 12;
-#ifndef DISABLE_IPV6_CHECKSUM
- if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset,
- sizeof(offset))
- < 0)
- zlog_warn("Network: set IPV6_CHECKSUM failed: %s",
- safe_strerror(errno));
-#else
- zlog_warn("Network: Don't set IPV6_CHECKSUM");
-#endif /* DISABLE_IPV6_CHECKSUM */
-}
-
void ospf6_serv_close(int *ospf6_sock)
{
if (*ospf6_sock != -1) {
@@ -113,7 +100,6 @@ int ospf6_serv_sock(struct ospf6 *ospf6)
ospf6_reset_mcastloop(ospf6_sock);
ospf6_set_pktinfo(ospf6_sock);
ospf6_set_transport_class(ospf6_sock);
- ospf6_set_checksum(ospf6_sock);
ospf6->fd = ospf6_sock;
/* setup global in6_addr, allspf6 and alldr6 for later use */
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index e60d2c7e0e..4d0c4ee59e 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -82,12 +82,16 @@ void ospf6_capability_printbuf(char capability, char *buf, int size)
void ospf6_options_printbuf(uint8_t *options, char *buf, int size)
{
- const char *dc, *r, *n, *mc, *e, *v6;
+ const char *dc, *r, *n, *mc, *e, *v6, *af, *at, *l;
dc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_DC) ? "DC" : "--");
r = (OSPF6_OPT_ISSET(options, OSPF6_OPT_R) ? "R" : "-");
n = (OSPF6_OPT_ISSET(options, OSPF6_OPT_N) ? "N" : "-");
mc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_MC) ? "MC" : "--");
e = (OSPF6_OPT_ISSET(options, OSPF6_OPT_E) ? "E" : "-");
v6 = (OSPF6_OPT_ISSET(options, OSPF6_OPT_V6) ? "V6" : "--");
- snprintf(buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6);
+ af = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_AF) ? "AF" : "--");
+ at = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_AT) ? "AT" : "--");
+ l = (OSPF6_OPT_ISSET_EXT(options, OSPF6_OPT_L) ? "L" : "-");
+ snprintf(buf, size, "%s|%s|%s|-|-|%s|%s|%s|%s|%s|%s", at, l, af, dc, r,
+ n, mc, e, v6);
}
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index b98dc38b72..ea476b3a8d 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -40,13 +40,20 @@
/* OSPF options */
/* present in HELLO, DD, LSA */
-#define OSPF6_OPT_SET(x,opt) ((x)[2] |= (opt))
-#define OSPF6_OPT_ISSET(x,opt) ((x)[2] & (opt))
-#define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt))
+#define OSPF6_OPT_SET(x, opt) ((x)[2] |= (opt))
+#define OSPF6_OPT_ISSET(x, opt) ((x)[2] & (opt))
+#define OSPF6_OPT_CLEAR(x, opt) ((x)[2] &= ~(opt))
+#define OSPF6_OPT_SET_EXT(x, opt) ((x)[1] |= (opt))
+#define OSPF6_OPT_ISSET_EXT(x, opt) ((x)[1] & (opt))
+#define OSPF6_OPT_CLEAR_EXT(x, opt) ((x)[1] &= ~(opt))
#define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0)
+#define OSPF6_OPT_AT (1 << 2) /* Authentication trailer Capability */
+#define OSPF6_OPT_L (1 << 1) /* Link local signalling Capability */
+#define OSPF6_OPT_AF (1 << 0) /* Address family Capability */
+/* 2 bits reserved for OSPFv2 migrated options */
#define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */
-#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
+#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index f5d60d80fa..3c74ca55c1 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -1168,7 +1168,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
json_object *json_routes, bool use_json)
{
char destination[PREFIX2STR_BUFFER], nexthop[64];
- char area_id[16], id[16], adv_router[16], capa[16], options[16];
+ char area_id[16], id[16], adv_router[16], capa[16], options[32];
char pfx_options[16];
struct timeval now, res;
char duration[64];
@@ -1653,7 +1653,7 @@ static void ospf6_linkstate_show_header(struct vty *vty)
static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route)
{
uint32_t router, id;
- char routername[16], idname[16], rbits[16], options[16];
+ char routername[16], idname[16], rbits[16], options[32];
router = ospf6_linkstate_prefix_adv_router(&route->prefix);
inet_ntop(AF_INET, &router, routername, sizeof(routername));
@@ -1779,7 +1779,7 @@ void ospf6_brouter_show_header(struct vty *vty)
void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route)
{
uint32_t adv_router;
- char adv[16], rbits[16], options[16], area[16];
+ char adv[16], rbits[16], options[32], area[16];
adv_router = ospf6_linkstate_prefix_adv_router(&route->prefix);
inet_ntop(AF_INET, &adv_router, adv, sizeof(adv));
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 57a55a6ef4..13f16efa66 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -54,6 +54,7 @@
#include "ospf6_gr.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
+#include "ospf6_auth_trailer.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_TOP, "OSPF6 top");
@@ -445,6 +446,17 @@ static struct ospf6 *ospf6_create(const char *name)
/* Make ospf protocol socket. */
ospf6_serv_sock(o);
+ /* If sequence number is stored in persistent storage, read it.
+ */
+ if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) {
+ ospf6_auth_seqno_nvm_read(o);
+ o->seqnum_h = o->seqnum_h + 1;
+ ospf6_auth_seqno_nvm_update(o);
+ } else {
+ o->seqnum_l = o->seqnum_h = 0;
+ ospf6_auth_seqno_nvm_update(o);
+ }
+
return o;
}
@@ -1386,6 +1398,10 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
json_object_int_add(json, "numberOfAreaInRouter",
listcount(o->area_list));
+ json_object_int_add(json, "AuthTrailerHigherSeqNo",
+ o->seqnum_h);
+ json_object_int_add(json, "AuthTrailerLowerSeqNo", o->seqnum_l);
+
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
if (CHECK_FLAG(o->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL))
@@ -1466,6 +1482,10 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
vty_out(vty, " Number of areas in this router is %u\n",
listcount(o->area_list));
+ vty_out(vty, " Authentication Sequence number info\n");
+ vty_out(vty, " Higher sequence no %u, Lower sequence no %u\n",
+ o->seqnum_h, o->seqnum_l);
+
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
if (CHECK_FLAG(o->config_flags,
OSPF6_LOG_ADJACENCY_DETAIL))
@@ -2117,7 +2137,7 @@ DEFPY (show_ipv6_ospf6_external_aggregator,
VRF_CMD_HELP_STR
"All VRFs\n"
"Show external summary addresses\n"
- "detailed informtion\n"
+ "detailed information\n"
JSON_STR)
{
bool uj = use_json(argc, argv);
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index b9f7235b46..f06a3254ac 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -228,6 +228,8 @@ struct ospf6 {
/* Action for aggregation of external LSAs */
int aggr_action;
+ uint32_t seqnum_l; /* lower order Sequence Number */
+ uint32_t seqnum_h; /* higher order Sequence Number */
#define OSPF6_EXTL_AGGR_DEFAULT_DELAY 5
/* For ASBR summary delay timer */
uint16_t aggr_delay_interval;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 82d280811b..e279d0411b 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -354,7 +354,7 @@ DEFUN(show_zebra,
vty_json(vty, json);
} else {
- vty_out(vty, "Zebra Infomation\n");
+ vty_out(vty, "Zebra Information\n");
vty_out(vty, " fail: %d\n", zclient->fail);
vty_out(vty, " redistribute default: %d\n",
vrf_bitmap_check(zclient->default_information[AFI_IP6],
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index cc5a0f7870..a16f4f73eb 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -48,6 +48,7 @@
#include "ospf6_gr.h"
#include "lib/json.h"
#include "ospf6_nssa.h"
+#include "ospf6_auth_trailer.h"
DEFINE_MGROUP(OSPF6D, "ospf6d");
@@ -98,6 +99,7 @@ static int config_write_ospf6_debug(struct vty *vty)
config_write_ospf6_debug_flood(vty);
config_write_ospf6_debug_nssa(vty);
config_write_ospf6_debug_gr_helper(vty);
+ config_write_ospf6_debug_auth(vty);
return 0;
}
@@ -1458,4 +1460,7 @@ void ospf6_init(struct thread_master *master)
VIEW_NODE,
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_database_aggr_router_cmd);
+ install_element_ospf6_debug_auth();
+ ospf6_interface_auth_trailer_cmd_init();
+ install_element_ospf6_clear_intf_auth();
}
diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am
index 34aabc205b..cf863ff523 100644
--- a/ospf6d/subdir.am
+++ b/ospf6d/subdir.am
@@ -24,6 +24,7 @@ vtysh_scan += \
ospf6d/ospf6_top.c \
ospf6d/ospf6_zebra.c \
ospf6d/ospf6d.c \
+ ospf6d/ospf6_auth_trailer.c \
# end
vtysh_daemons += ospf6d
if SNMP
@@ -56,6 +57,7 @@ ospf6d_libospf6_a_SOURCES = \
ospf6d/ospf6_top.c \
ospf6d/ospf6_zebra.c \
ospf6d/ospf6d.c \
+ ospf6d/ospf6_auth_trailer.c \
# end
noinst_HEADERS += \
@@ -80,6 +82,7 @@ noinst_HEADERS += \
ospf6d/ospf6_top.h \
ospf6d/ospf6_zebra.h \
ospf6d/ospf6d.h \
+ ospf6d/ospf6_auth_trailer.h \
# end
ospf6d_ospf6d_LDADD = ospf6d/libospf6.a lib/libfrr.la $(LIBCAP)
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index f44e1dde82..db78e6d2df 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -207,7 +207,7 @@ struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf,
struct as_external_lsa *al;
struct in_addr mask, id;
- /* Fisrt search the lsdb with address specifc LSID
+ /* First search the lsdb with address specific LSID
* where all the host bits are set, if there a matched
* LSA, return.
* Ex: For route 10.0.0.0/16, LSID is 10.0.255.255
@@ -630,7 +630,7 @@ struct ospf_lsa *ospf_originate_summary_lsa(struct ospf *ospf,
ospf_link_ei_to_aggr(aggr, ei);
lsa = ospf_external_info_find_lsa(ospf, &aggr->p);
- /* Dont originate external LSA,
+ /* Don't originate external LSA,
* If it is configured not to advertise.
*/
if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) {
@@ -787,12 +787,12 @@ static void ospf_handle_aggregated_exnl_rt(struct ospf *ospf,
/* Handling the case where the external route prefix
* and aggregate prefix is same
- * If same dont flush the originated external LSA.
+ * If same don't flush the originated external LSA.
*/
if (prefix_same((struct prefix *)&aggr->p, (struct prefix *)&ei->p)) {
if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
zlog_debug(
- "%s: External Route prefix same as Aggregator(%pI4/%d), so dont flush.",
+ "%s: External Route prefix same as Aggregator(%pI4/%d), so don't flush.",
__func__, &ei->p.prefix, ei->p.prefixlen);
return;
}
diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c
index ae002fdc97..5eca591754 100644
--- a/ospfd/ospf_gr_helper.c
+++ b/ospfd/ospf_gr_helper.c
@@ -847,8 +847,8 @@ void ospf_gr_helper_support_set(struct ospf *ospf, bool support)
lookup.advRtrAddr.s_addr =
nbr->router_id.s_addr;
/* check if helper support enabled for the
- * corresponding routerid.If enabled, dont
- * dont exit from helper role.
+ * corresponding routerid.If enabled, don't
+ * exit from helper role.
*/
if (hash_lookup(ospf->enable_rtr_list, &lookup))
continue;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 32d87b9a91..0b7c3c6831 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -10398,7 +10398,7 @@ DEFPY (show_ip_ospf_gr_helper,
"All VRFs\n"
"OSPF Graceful Restart\n"
"Helper details in the router\n"
- "Detailed informtion\n"
+ "Detailed information\n"
JSON_STR)
{
char *vrf_name = NULL;
@@ -11500,7 +11500,7 @@ DEFUN (show_ip_ospf_external_aggregator,
VRF_CMD_HELP_STR
"All VRFs\n"
"Show external summary addresses\n"
- "Detailed informtion\n"
+ "Detailed information\n"
JSON_STR)
{
char *vrf_name = NULL;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 7834b7d934..66b7425a81 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1380,7 +1380,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
/* Handling the case where the
* external route prefix
* and aggegate prefix is same
- * If same dont flush the
+ * If same don't flush the
* originated
* external LSA.
*/
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index e5f3eec603..b1bba9eb4e 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1089,7 +1089,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
ospf_ldp_sync_if_init(oi);
/*
- * if router_id is not configured, dont bring up
+ * if router_id is not configured, don't bring up
* interfaces.
* ospf_router_id_update() will call ospf_if_update
* whenever r-id is configured instead.
diff --git a/pathd/path_errors.c b/pathd/path_errors.c
index 112a3d5ee9..68372c29b6 100644
--- a/pathd/path_errors.c
+++ b/pathd/path_errors.c
@@ -81,7 +81,7 @@ static struct log_ref ferr_path_warn[] = {
{
.code = EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
.title = "Unsupported PCEP feature",
- .description = "Receved an unsupported PCEP message",
+ .description = "Received an unsupported PCEP message",
.suggestion = "The PCC and PCE are probably not compatible. Open an Issue with all relevant log files"
},
{
diff --git a/pathd/path_pcep_config.c b/pathd/path_pcep_config.c
index 4c16b83948..99b1c349a9 100644
--- a/pathd/path_pcep_config.c
+++ b/pathd/path_pcep_config.c
@@ -301,7 +301,7 @@ int path_pcep_config_initiate_path(struct path *path)
return ERROR_19_9;
}
zlog_warn(
- "(%s)PCE tried to REMOVE found canidate!, let's remove",
+ "(%s)PCE tried to REMOVE found candidate!, let's remove",
__func__);
candidate->policy->srp_id = path->srp_id;
SET_FLAG(candidate->policy->flags, F_POLICY_DELETED);
diff --git a/pathd/pathd.c b/pathd/pathd.c
index 7f6d34f752..f56da37b51 100644
--- a/pathd/pathd.c
+++ b/pathd/pathd.c
@@ -1345,7 +1345,7 @@ int32_t srte_ted_do_query_type_c(struct srte_segment_entry *entry,
zlog_warn(" %s: PATHD-TED: SL: ERROR query C : ted-sid (%d)",
__func__, ted_sid);
} else {
- zlog_debug("%s: PATHD-TED: SL: Sucess query C : ted-sid (%d)",
+ zlog_debug("%s: PATHD-TED: SL: Success query C : ted-sid (%d)",
__func__, ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
@@ -1375,7 +1375,7 @@ int32_t srte_ted_do_query_type_e(struct srte_segment_entry *entry,
zlog_warn(" %s: PATHD-TED: SL: ERROR query E : ted-sid (%d)",
__func__, ted_sid);
} else {
- zlog_debug("%s: PATHD-TED: SL: Sucess query E : ted-sid (%d)",
+ zlog_debug("%s: PATHD-TED: SL: Success query E : ted-sid (%d)",
__func__, ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
@@ -1404,7 +1404,7 @@ int32_t srte_ted_do_query_type_f(struct srte_segment_entry *entry,
zlog_warn("%s:SL: ERROR query F : ted-sid (%d)", __func__,
ted_sid);
} else {
- zlog_debug("%s:SL: Sucess query F : ted-sid (%d)", __func__,
+ zlog_debug("%s:SL: Success query F : ted-sid (%d)", __func__,
ted_sid);
}
if (CHECK_SID(entry->segment_list->protocol_origin, ted_sid,
diff --git a/pceplib/pcep_timers.c b/pceplib/pcep_timers.c
index bbf9b77983..b0f3e70b50 100644
--- a/pceplib/pcep_timers.c
+++ b/pceplib/pcep_timers.c
@@ -413,7 +413,7 @@ bool reset_timer(int timer_id)
/* Keeping this log for now, since in older versions of FRR the
* timer cancellation was blocking. This allows us to see how
* long the it takes.*/
- pcep_log(LOG_DEBUG, "%s: Reseting timer [%d] with callback",
+ pcep_log(LOG_DEBUG, "%s: Resetting timer [%d] with callback",
__func__, timer_to_reset->timer_id);
timers_context_->timer_cancel_func(
&timer_to_reset->external_timer);
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index 3c38ebd76b..7d05403c36 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -61,18 +61,11 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
ch->interface->name);
}
- if (winner_changed) {
- char was_str[INET_ADDRSTRLEN];
- char winner_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<was?>", ch->ifassert_winner, was_str,
- sizeof(was_str));
- pim_inet4_dump("<winner?>", winner, winner_str,
- sizeof(winner_str));
+ if (winner_changed)
zlog_debug(
- "%s: (S,G)=%s assert winner changed from %s to %s on interface %s",
- __func__, ch->sg_str, was_str, winner_str,
- ch->interface->name);
- }
+ "%s: (S,G)=%s assert winner changed from %pPAs to %pPAs on interface %s",
+ __func__, ch->sg_str, &ch->ifassert_winner,
+ &winner, ch->interface->name);
} /* PIM_DEBUG_PIM_EVENTS */
ch->ifassert_state = new_state;
@@ -87,14 +80,10 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
}
}
-static void on_trace(const char *label, struct interface *ifp,
- struct in_addr src)
+static void on_trace(const char *label, struct interface *ifp, pim_addr src)
{
- if (PIM_DEBUG_PIM_TRACE) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
- zlog_debug("%s: from %s on %s", label, src_str, ifp->name);
- }
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug("%s: from %pPAs on %s", label, &src, ifp->name);
}
static int preferred_assert(const struct pim_ifchannel *ch,
@@ -136,8 +125,8 @@ static void if_could_assert_do_a1(const char *caller, struct pim_ifchannel *ch)
}
}
-static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,
- struct in_addr group_addr,
+static int dispatch_assert(struct interface *ifp, pim_addr source_addr,
+ pim_addr group_addr,
struct pim_assert_metric recv_metric)
{
struct pim_ifchannel *ch;
@@ -213,10 +202,11 @@ static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,
}
int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
- struct in_addr src_addr, uint8_t *buf, int buf_size)
+ pim_addr src_addr, uint8_t *buf, int buf_size)
{
pim_sgaddr sg;
- struct prefix msg_source_addr;
+ pim_addr msg_source_addr;
+ bool wrong_af = false;
struct pim_assert_metric msg_metric;
int offset;
uint8_t *curr;
@@ -234,10 +224,9 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
memset(&sg, 0, sizeof(sg));
offset = pim_parse_addr_group(&sg, curr, curr_size);
if (offset < 1) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s",
- __func__, src_str, ifp->name);
+ zlog_warn(
+ "%s: pim_parse_addr_group() failure: from %pPAs on %s",
+ __func__, &src_addr, ifp->name);
return -1;
}
curr += offset;
@@ -246,23 +235,21 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Parse assert source addr
*/
- offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size);
- if (offset < 1) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
- __func__, src_str, ifp->name);
+ offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size,
+ &wrong_af);
+ if (offset < 1 || wrong_af) {
+ zlog_warn(
+ "%s: pim_parse_addr_ucast() failure: from %pPAs on %s",
+ __func__, &src_addr, ifp->name);
return -2;
}
curr += offset;
curr_size -= offset;
if (curr_size < 8) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
zlog_warn(
- "%s: preference/metric size is less than 8 bytes: size=%d from %s on interface %s",
- __func__, curr_size, src_str, ifp->name);
+ "%s: preference/metric size is less than 8 bytes: size=%d from %pPAs on interface %s",
+ __func__, curr_size, &src_addr, ifp->name);
return -3;
}
@@ -284,19 +271,13 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
msg_metric.route_metric = pim_read_uint32_host(curr);
- if (PIM_DEBUG_PIM_TRACE) {
- char neigh_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<neigh?>", src_addr, neigh_str,
- sizeof(neigh_str));
- pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str,
- sizeof(source_str));
+ if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
- "%s: from %s on %s: (S,G)=(%s,%pPAs) pref=%u metric=%u rpt_bit=%u",
- __func__, neigh_str, ifp->name, source_str, &sg.grp,
- msg_metric.metric_preference, msg_metric.route_metric,
+ "%s: from %pPAs on %s: (S,G)=(%pPAs,%pPAs) pref=%u metric=%u rpt_bit=%u",
+ __func__, &src_addr, ifp->name, &msg_source_addr,
+ &sg.grp, msg_metric.metric_preference,
+ msg_metric.route_metric,
PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag));
- }
msg_metric.ip_address = src_addr;
@@ -304,8 +285,7 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
assert(pim_ifp);
++pim_ifp->pim_ifstat_assert_recv;
- return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp,
- msg_metric);
+ return dispatch_assert(ifp, msg_source_addr, sg.grp, msg_metric);
}
/*
@@ -354,7 +334,7 @@ int pim_assert_metric_match(const struct pim_assert_metric *m1,
}
int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp,
- struct in_addr group_addr, struct in_addr source_addr,
+ pim_addr group_addr, pim_addr source_addr,
uint32_t metric_preference, uint32_t route_metric,
uint32_t rpt_bit_flag)
{
@@ -368,28 +348,21 @@ int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp,
/* Encode group */
remain = buf_pastend - pim_msg_curr;
- pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr);
+ pim_msg_curr = pim_msg_addr_encode_group(pim_msg_curr, group_addr);
if (!pim_msg_curr) {
- char group_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<grp?>", group_addr, group_str,
- sizeof(group_str));
zlog_warn(
- "%s: failure encoding group address %s: space left=%d",
- __func__, group_str, remain);
+ "%s: failure encoding group address %pPA: space left=%d",
+ __func__, &group_addr, remain);
return -1;
}
/* Encode source */
remain = buf_pastend - pim_msg_curr;
- pim_msg_curr =
- pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr);
+ pim_msg_curr = pim_msg_addr_encode_ucast(pim_msg_curr, source_addr);
if (!pim_msg_curr) {
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", source_addr, source_str,
- sizeof(source_str));
zlog_warn(
- "%s: failure encoding source address %s: space left=%d",
- __func__, source_str, remain);
+ "%s: failure encoding source address %pPA: space left=%d",
+ __func__, &source_addr, remain);
return -2;
}
diff --git a/pimd/pim_assert.h b/pimd/pim_assert.h
index a149fb176e..22bab67c59 100644
--- a/pimd/pim_assert.h
+++ b/pimd/pim_assert.h
@@ -59,7 +59,7 @@ void pim_ifassert_winner_set(struct pim_ifchannel *ch,
struct pim_assert_metric winner_metric);
int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
- struct in_addr src_addr, uint8_t *buf, int buf_size);
+ pim_addr src_addr, uint8_t *buf, int buf_size);
int pim_assert_metric_better(const struct pim_assert_metric *m1,
const struct pim_assert_metric *m2);
@@ -67,7 +67,7 @@ int pim_assert_metric_match(const struct pim_assert_metric *m1,
const struct pim_assert_metric *m2);
int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp,
- struct in_addr group_addr, struct in_addr source_addr,
+ pim_addr group_addr, pim_addr source_addr,
uint32_t metric_preference, uint32_t route_metric,
uint32_t rpt_bit_flag);
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 31f672bb80..3e3021dc4d 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -94,7 +94,11 @@ void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp,
bfd_sess_set_timers(
neigh->bfd_session, pim_ifp->bfd_config.detection_multiplier,
pim_ifp->bfd_config.min_rx, pim_ifp->bfd_config.min_tx);
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
bfd_sess_set_ipv4_addrs(neigh->bfd_session, NULL, &neigh->source_addr);
+#else
+ bfd_sess_set_ipv6_addrs(neigh->bfd_session, NULL, &neigh->source_addr);
+#endif
bfd_sess_set_interface(neigh->bfd_session, neigh->interface->name);
bfd_sess_set_vrf(neigh->bfd_session, neigh->interface->vrf->vrf_id);
bfd_sess_set_profile(neigh->bfd_session, pim_ifp->bfd_config.profile);
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 4214790476..0b993ec05e 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -667,10 +667,7 @@ void pim_bsm_clear(struct pim_instance *pim)
struct prefix grp;
struct rp_info *trp_info;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
-
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
/* RP not found for the group grp */
@@ -690,7 +687,7 @@ void pim_bsm_clear(struct pim_instance *pim)
}
static bool pim_bsm_send_intf(uint8_t *buf, int len, struct interface *ifp,
- struct in_addr dst_addr)
+ pim_addr dst_addr)
{
struct pim_interface *pim_ifp;
@@ -723,8 +720,7 @@ static bool pim_bsm_send_intf(uint8_t *buf, int len, struct interface *ifp,
}
static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
- uint32_t pim_mtu, struct in_addr dst_addr,
- bool no_fwd)
+ uint32_t pim_mtu, pim_addr dst_addr, bool no_fwd)
{
struct bsmmsg_grpinfo *grpinfo, *curgrp;
uint8_t *firstgrp_ptr;
@@ -895,7 +891,7 @@ static void pim_bsm_fwd_whole_sz(struct pim_instance *pim, uint8_t *buf,
{
struct interface *ifp;
struct pim_interface *pim_ifp;
- struct in_addr dst_addr;
+ pim_addr dst_addr;
uint32_t pim_mtu;
bool no_fwd = false;
bool ret = false;
@@ -942,7 +938,7 @@ static void pim_bsm_fwd_whole_sz(struct pim_instance *pim, uint8_t *buf,
bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
{
- struct in_addr dst_addr;
+ pim_addr dst_addr;
struct pim_interface *pim_ifp;
struct bsm_scope *scope;
struct bsm_frag *bsfrag;
@@ -951,17 +947,14 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
bool no_fwd = true;
bool ret = false;
- if (PIM_DEBUG_BSM) {
- pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str,
- sizeof(neigh_src_str));
- zlog_debug("%s: New neighbor %s seen on %s", __func__,
- neigh_src_str, ifp->name);
- }
+ if (PIM_DEBUG_BSM)
+ zlog_debug("%s: New neighbor %pPA seen on %s", __func__,
+ &neigh->source_addr, ifp->name);
pim_ifp = ifp->info;
/* DR only forwards BSM packet */
- if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) {
+ if (!pim_addr_cmp(pim_ifp->pim_dr_addr, pim_ifp->primary_address)) {
if (PIM_DEBUG_BSM)
zlog_debug(
"%s: It is not DR, so don't forward BSM packet",
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 2baaca1c9f..83ba74f69f 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -2427,9 +2427,9 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
struct pim_neighbor *nbr;
- nbr = pim_neighbor_find(
+ nbr = pim_neighbor_find_prefix(
up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ &up->rpf.rpf_addr);
if (nbr)
pim_time_timer_to_hhmmss(join_timer,
sizeof(join_timer),
@@ -3488,15 +3488,24 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
} /* scan interfaces */
}
-static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
+static void igmp_show_sources(struct pim_instance *pim, struct vty *vty,
+ bool uj)
{
struct interface *ifp;
time_t now;
+ json_object *json = NULL;
+ json_object *json_iface = NULL;
+ json_object *json_group = NULL;
+ json_object *json_source = NULL;
+ json_object *json_sources = NULL;
now = pim_time_monotonic_sec();
- vty_out(vty,
- "Interface Group Source Timer Fwd Uptime \n");
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "Interface Address Group Source Timer Fwd Uptime \n");
/* scan interfaces */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3533,17 +3542,70 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
pim_time_uptime(uptime, sizeof(uptime),
now - src->source_creation);
- vty_out(vty, "%-16s %-15s %-15s %5s %3s %8s\n",
- ifp->name, group_str, source_str, mmss,
- IGMP_SOURCE_TEST_FORWARDING(
- src->source_flags)
- ? "Y"
- : "N",
- uptime);
+ if (uj) {
+ json_object_object_get_ex(
+ json, ifp->name, &json_iface);
+ if (!json_iface) {
+ json_iface =
+ json_object_new_object();
+ json_object_string_add(
+ json_iface, "name",
+ ifp->name);
+ json_object_object_add(
+ json, ifp->name,
+ json_iface);
+ }
+ json_object_object_get_ex(json_iface,
+ group_str,
+ &json_group);
+
+ if (!json_group) {
+ json_group =
+ json_object_new_object();
+ json_object_string_add(
+ json_group, "group",
+ group_str);
+ json_object_object_add(
+ json_iface, group_str,
+ json_group);
+ json_sources =
+ json_object_new_array();
+ json_object_object_add(
+ json_group, "sources",
+ json_sources);
+ }
+ json_source = json_object_new_object();
+ json_object_string_add(json_source,
+ "source",
+ source_str);
+ json_object_string_add(json_source,
+ "timer", mmss);
+ json_object_boolean_add(
+ json_source, "forwarded",
+ IGMP_SOURCE_TEST_FORWARDING(
+ src->source_flags));
+ json_object_string_add(
+ json_source, "uptime", uptime);
+ json_object_array_add(json_sources,
+ json_source);
+
+ } else {
+ vty_out(vty,
+ "%-16s %-15s %-15s %5s %3s %8s\n",
+ ifp->name, group_str,
+ source_str, mmss,
+ IGMP_SOURCE_TEST_FORWARDING(
+ src->source_flags)
+ ? "Y"
+ : "N",
+ uptime);
+ }
} /* scan group sources */
} /* scan igmp groups */
} /* scan interfaces */
+ if (uj)
+ vty_json(vty, json);
}
static void igmp_show_source_retransmission(struct pim_instance *pim,
@@ -4189,12 +4251,13 @@ DEFUN (show_ip_igmp_groups_retransmissions,
DEFUN (show_ip_igmp_sources,
show_ip_igmp_sources_cmd,
- "show ip igmp [vrf NAME] sources",
+ "show ip igmp [vrf NAME] sources [json]",
SHOW_STR
IP_STR
IGMP_STR
VRF_CMD_HELP_STR
- IGMP_SOURCE_STR)
+ IGMP_SOURCE_STR
+ JSON_STR)
{
int idx = 2;
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
@@ -4202,7 +4265,7 @@ DEFUN (show_ip_igmp_sources,
if (!vrf)
return CMD_WARNING;
- igmp_show_sources(vrf->info, vty);
+ igmp_show_sources(vrf->info, vty, use_json(argc, argv));
return CMD_SUCCESS;
}
@@ -8174,7 +8237,8 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate,
"IGMP version number\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- int igmp_version = 2;
+ int igmp_version;
+ struct pim_interface *pim_ifp = ifp->info;
if (!ifp->info) {
vty_out(vty, "IGMP/PIM is not enabled on the interface %s\n",
@@ -8182,6 +8246,9 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate,
return CMD_WARNING_CONFIG_FAILED;
}
+ /* It takes the igmp version configured on the interface as default */
+ igmp_version = pim_ifp->igmp_version;
+
if (argc > 3)
igmp_version = atoi(argv[4]->arg);
diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c
index 45ea6a9562..fe4f10aa6a 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -33,81 +33,62 @@
#include "pim_upstream.h"
#include "pim_bsm.h"
-static void on_trace(const char *label, struct interface *ifp,
- struct in_addr src)
+static void on_trace(const char *label, struct interface *ifp, pim_addr src)
{
- if (PIM_DEBUG_PIM_TRACE) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
- zlog_debug("%s: from %s on %s", label, src_str, ifp->name);
- }
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug("%s: from %pPAs on %s", label, &src, ifp->name);
}
static void tlv_trace_bool(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
- int isset, int value)
+ const char *ifname, pim_addr src_addr, int isset,
+ int value)
{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (isset)
zlog_debug(
- "%s: PIM hello option from %s on interface %s: %s=%d",
- label, src_str, ifname, tlv_name, value);
- }
+ "%s: PIM hello option from %pPAs on interface %s: %s=%d",
+ label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint16(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
- int isset, uint16_t value)
+ const char *ifname, pim_addr src_addr, int isset,
+ uint16_t value)
{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (isset)
zlog_debug(
- "%s: PIM hello option from %s on interface %s: %s=%u",
- label, src_str, ifname, tlv_name, value);
- }
+ "%s: PIM hello option from %pPAs on interface %s: %s=%u",
+ label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint32(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
- int isset, uint32_t value)
+ const char *ifname, pim_addr src_addr, int isset,
+ uint32_t value)
{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (isset)
zlog_debug(
- "%s: PIM hello option from %s on interface %s: %s=%u",
- label, src_str, ifname, tlv_name, value);
- }
+ "%s: PIM hello option from %pPAs on interface %s: %s=%u",
+ label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint32_hex(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
+ const char *ifname, pim_addr src_addr,
int isset, uint32_t value)
{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (isset)
zlog_debug(
- "%s: PIM hello option from %s on interface %s: %s=%08x",
- label, src_str, ifname, tlv_name, value);
- }
+ "%s: PIM hello option from %pPAs on interface %s: %s=%08x",
+ label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_list(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
- int isset, struct list *addr_list)
+ const char *ifname, pim_addr src_addr, int isset,
+ struct list *addr_list)
{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (isset)
zlog_debug(
- "%s: PIM hello option from %s on interface %s: %s size=%d list=%p",
- label, src_str, ifname, tlv_name,
+ "%s: PIM hello option from %pPAs on interface %s: %s size=%d list=%p",
+ label, &src_addr, ifname, tlv_name,
addr_list ? ((int)listcount(addr_list)) : -1,
(void *)addr_list);
- }
}
#define FREE_ADDR_LIST \
@@ -121,8 +102,8 @@ static void tlv_trace_list(const char *label, const char *tlv_name,
return (code); \
}
-int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
- uint8_t *tlv_buf, int tlv_buf_size)
+int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf,
+ int tlv_buf_size)
{
struct pim_interface *pim_ifp;
struct pim_neighbor *neigh;
@@ -158,15 +139,11 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
int remain = tlv_pastend - tlv_curr;
if (remain < PIM_TLV_MIN_SIZE) {
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: short PIM hello TLV size=%d < min=%d from %s on interface %s",
+ "%s: short PIM hello TLV size=%d < min=%d from %pPAs on interface %s",
__func__, remain, PIM_TLV_MIN_SIZE,
- src_str, ifp->name);
- }
+ &src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-1);
}
@@ -176,28 +153,20 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
tlv_curr += PIM_TLV_LENGTH_SIZE;
if ((tlv_curr + option_len) > tlv_pastend) {
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s",
+ "%s: long PIM hello TLV type=%d length=%d > left=%td from %pPAs on interface %s",
__func__, option_type, option_len,
- tlv_pastend - tlv_curr, src_str,
+ tlv_pastend - tlv_curr, &src_addr,
ifp->name);
- }
FREE_ADDR_LIST_THEN_RETURN(-2);
}
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s",
+ "%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %pPAs on %s",
__func__, remain, option_type, option_len,
- src_str, ifp->name);
- }
+ &src_addr, ifp->name);
switch (option_type) {
case PIM_MSG_OPTION_TYPE_HOLDTIME:
@@ -242,26 +211,18 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
break;
case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH:
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s",
+ "%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %pPAs on interface %s",
__func__, option_type, option_len,
- src_str, ifp->name);
- }
+ &src_addr, ifp->name);
break;
default:
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s",
+ "%s: ignoring unknown PIM hello TLV type=%d length=%d from %pPAs on interface %s",
__func__, option_type, option_len,
- src_str, ifp->name);
- }
+ &src_addr, ifp->name);
}
tlv_curr += option_len;
@@ -310,14 +271,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: PIM hello missing holdtime from %s on interface %s",
- __func__, src_str, ifp->name);
- }
+ "%s: PIM hello missing holdtime from %pPAs on interface %s",
+ __func__, &src_addr, ifp->name);
}
/*
@@ -335,14 +292,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
hello_option_dr_priority, hello_option_generation_id,
hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY);
if (!neigh) {
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_warn(
- "%s: failure creating PIM neighbor %s on interface %s",
- __func__, src_str, ifp->name);
- }
+ "%s: failure creating PIM neighbor %pPAs on interface %s",
+ __func__, &src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-8);
}
/* Forward BSM if required */
@@ -368,16 +321,12 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
|| (hello_option_generation_id != neigh->generation_id)) {
/* GenID mismatch, then replace neighbor */
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s",
+ "%s: GenId mismatch new=%08x old=%08x: replacing neighbor %pPAs on %s",
__func__, hello_option_generation_id,
- neigh->generation_id, src_str,
+ neigh->generation_id, &src_addr,
ifp->name);
- }
pim_upstream_rpf_genid_changed(pim_ifp->pim,
neigh->source_addr);
@@ -392,15 +341,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
hello_option_addr_list,
PIM_NEIGHBOR_SEND_NOW);
if (!neigh) {
- if (PIM_DEBUG_PIM_HELLO) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr,
- src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
- "%s: failure re-creating PIM neighbor %s on interface %s",
- __func__, src_str, ifp->name);
- }
+ "%s: failure re-creating PIM neighbor %pPAs on interface %s",
+ __func__, &src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-9);
}
/* Forward BSM if required */
diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h
index df41f97d9e..56084e06d2 100644
--- a/pimd/pim_hello.h
+++ b/pimd/pim_hello.h
@@ -24,8 +24,8 @@
#include "if.h"
-int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
- uint8_t *tlv_buf, int tlv_buf_size);
+int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf,
+ int tlv_buf_size);
int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
int tlv_buf_size, uint16_t holdtime,
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 3f138e22e5..57fe97816e 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -193,7 +193,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
void pim_if_delete(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
assert(ifp);
pim_ifp = ifp->info;
@@ -218,13 +217,6 @@ void pim_if_delete(struct interface *ifp)
list_delete(&pim_ifp->sec_addr_list);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
-
- while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
- ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
-
- pim_ifchannel_delete(ch);
- }
-
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
ifp->info = NULL;
@@ -299,27 +291,20 @@ static int detect_primary_address_change(struct interface *ifp,
const char *caller)
{
struct pim_interface *pim_ifp = ifp->info;
- struct in_addr new_prim_addr;
+ pim_addr new_prim_addr;
int changed;
if (force_prim_as_any)
- new_prim_addr.s_addr = INADDR_ANY;
+ new_prim_addr = PIMADDR_ANY;
else
new_prim_addr = pim_find_primary_addr(ifp);
- changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
+ changed = pim_addr_cmp(new_prim_addr, pim_ifp->primary_address);
- if (PIM_DEBUG_ZEBRA) {
- char new_prim_str[INET_ADDRSTRLEN];
- char old_prim_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<new?>", new_prim_addr, new_prim_str,
- sizeof(new_prim_str));
- pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str,
- sizeof(old_prim_str));
- zlog_debug("%s: old=%s new=%s on interface %s: %s", __func__,
- old_prim_str, new_prim_str, ifp->name,
- changed ? "changed" : "unchanged");
- }
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
+ __func__, &pim_ifp->primary_address, &new_prim_addr,
+ ifp->name, changed ? "changed" : "unchanged");
if (changed) {
/* Before updating pim_ifp send Hello time with 0 hold time */
@@ -401,19 +386,18 @@ static int pim_sec_addr_update(struct interface *ifp)
}
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
- struct prefix *p = ifc->address;
+ pim_addr addr = pim_addr_from_prefix(ifc->address);
- if (p->u.prefix4.s_addr == INADDR_ANY) {
+ if (pim_addr_is_any(addr))
continue;
- }
- if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
+ if (!pim_addr_cmp(addr, pim_ifp->primary_address)) {
/* don't add the primary address into the secondary
* address list */
continue;
}
- if (pim_sec_addr_add(pim_ifp, p)) {
+ if (pim_sec_addr_add(pim_ifp, ifc->address)) {
changed = 1;
}
}
@@ -480,7 +464,7 @@ static void detect_address_change(struct interface *ifp, int force_prim_as_any,
* address change on all of them when the lo address changes */
}
-int pim_update_source_set(struct interface *ifp, struct in_addr source)
+int pim_update_source_set(struct interface *ifp, pim_addr source)
{
struct pim_interface *pim_ifp = ifp->info;
@@ -488,7 +472,7 @@ int pim_update_source_set(struct interface *ifp, struct in_addr source)
return PIM_IFACE_NOT_FOUND;
}
- if (pim_ifp->update_source.s_addr == source.s_addr) {
+ if (!pim_addr_cmp(pim_ifp->update_source, source)) {
return PIM_UPDATE_SOURCE_DUP;
}
@@ -827,11 +811,10 @@ void pim_if_addr_del_all_igmp(struct interface *ifp)
}
}
-struct in_addr pim_find_primary_addr(struct interface *ifp)
+pim_addr pim_find_primary_addr(struct interface *ifp)
{
struct connected *ifc;
struct listnode *node;
- struct in_addr addr = {0};
int v4_addrs = 0;
int v6_addrs = 0;
struct pim_interface *pim_ifp = ifp->info;
@@ -841,28 +824,35 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
}
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
- struct prefix *p = ifc->address;
+ pim_addr addr;
- if (p->family != AF_INET) {
+ switch (ifc->address->family) {
+ case AF_INET:
+ v4_addrs++;
+ break;
+ case AF_INET6:
v6_addrs++;
+ break;
+ default:
continue;
}
- if (p->u.prefix4.s_addr == INADDR_ANY) {
- zlog_warn(
- "%s: null IPv4 address connected to interface %s",
- __func__, ifp->name);
+ if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
continue;
- }
- v4_addrs++;
-
- if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+ if (ifc->address->family != PIM_AF)
continue;
- return p->u.prefix4;
+ addr = pim_addr_from_prefix(ifc->address);
+
+#if PIM_IPV == 6
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr))
+ continue;
+#endif
+ return addr;
}
+#if PIM_IPV == 4
/*
* If we have no v4_addrs and v6 is configured
* We probably are using unnumbered
@@ -882,10 +872,8 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
if (lo_ifp && (lo_ifp != ifp))
return pim_find_primary_addr(lo_ifp);
}
-
- addr.s_addr = PIM_NET_INADDR_ANY;
-
- return addr;
+#endif
+ return PIMADDR_ANY;
}
static int pim_iface_next_vif_index(struct interface *ifp)
@@ -1094,8 +1082,7 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
router (Section 4.3.4). The primary IP address of a neighbor is the
address that it uses as the source of its PIM Hello messages.
*/
-struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
- struct in_addr addr)
+struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr)
{
struct listnode *neighnode;
struct pim_neighbor *neigh;
@@ -1111,15 +1098,13 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
return 0;
}
- p.family = AF_INET;
- p.u.prefix4 = addr;
- p.prefixlen = IPV4_MAX_BITLEN;
+ pim_addr_to_prefix(&p, addr);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
neigh)) {
/* primary address ? */
- if (neigh->source_addr.s_addr == addr.s_addr)
+ if (!pim_addr_cmp(neigh->source_addr, addr))
return neigh;
/* secondary address ? */
@@ -1127,13 +1112,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
return neigh;
}
- if (PIM_DEBUG_PIM_TRACE) {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+ if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
- "%s: neighbor not found for address %s on interface %s",
- __func__, addr_str, ifp->name);
- }
+ "%s: neighbor not found for address %pPA on interface %s",
+ __func__, &addr, ifp->name);
return NULL;
}
@@ -1383,8 +1365,7 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)
gone down (and may have come back up), and so we must assume it no
longer knows it was the winner.
*/
-void pim_if_assert_on_neighbor_down(struct interface *ifp,
- struct in_addr neigh_addr)
+void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr)
{
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
@@ -1397,7 +1378,7 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
continue;
/* Dead neighbor was winner ? */
- if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
+ if (pim_addr_cmp(ch->ifassert_winner, neigh_addr))
continue;
assert_action_a5(ch);
@@ -1473,7 +1454,7 @@ void pim_if_create_pimreg(struct pim_instance *pim)
}
}
-struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
+struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src)
{
struct listnode *cnode;
struct connected *c;
@@ -1482,12 +1463,10 @@ struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr
if (!ifp)
return NULL;
- p.family = AF_INET;
- p.u.prefix4 = src;
- p.prefixlen = IPV4_MAX_BITLEN;
+ pim_addr_to_prefix(&p, src);
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
- if (c->address->family != AF_INET)
+ if (c->address->family != PIM_AF)
continue;
if (prefix_match(c->address, &p))
return c->address;
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index 1ddf743619..00ec8e7427 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -59,7 +59,8 @@
#define PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPPRESSION(options) \
((options) &= ~PIM_IF_MASK_PIM_CAN_DISABLE_JOIN_SUPPRESSION)
-#define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr
+#define PIM_I_am_DR(pim_ifp) \
+ !pim_addr_cmp((pim_ifp)->pim_dr_addr, (pim_ifp)->primary_address)
#define PIM_I_am_DualActive(pim_ifp) (pim_ifp)->activeactive == true
/* Macros for interface flags */
@@ -225,13 +226,12 @@ int pim_if_lan_delay_enabled(struct interface *ifp);
uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp);
uint16_t pim_if_effective_override_interval_msec(struct interface *ifp);
uint16_t pim_if_jp_override_interval_msec(struct interface *ifp);
-struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
- struct in_addr addr);
+struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr);
long pim_if_t_suppressed_msec(struct interface *ifp);
int pim_if_t_override_msec(struct interface *ifp);
-struct in_addr pim_find_primary_addr(struct interface *ifp);
+pim_addr pim_find_primary_addr(struct interface *ifp);
ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
struct in_addr source_addr);
@@ -240,8 +240,7 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
void pim_if_update_could_assert(struct interface *ifp);
-void pim_if_assert_on_neighbor_down(struct interface *ifp,
- struct in_addr neigh_addr);
+void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr);
void pim_if_rpf_interface_changed(struct interface *old_rpf_ifp,
struct pim_upstream *up);
@@ -252,8 +251,8 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp);
void pim_if_create_pimreg(struct pim_instance *pim);
-struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
-int pim_update_source_set(struct interface *ifp, struct in_addr source);
+struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src);
+int pim_update_source_set(struct interface *ifp, pim_addr source);
bool pim_if_is_vrf_device(struct interface *ifp);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 9248177724..a613c89b7e 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -423,11 +423,9 @@ const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state)
*/
void reset_ifassert_state(struct pim_ifchannel *ch)
{
- struct in_addr any = {.s_addr = INADDR_ANY};
-
THREAD_OFF(ch->t_ifassert_timer);
- pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any,
+ pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, PIMADDR_ANY,
router->infinite_assert_metric);
}
@@ -587,7 +585,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg,
ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch);
ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch);
- ch->ifassert_winner.s_addr = INADDR_ANY;
+ ch->ifassert_winner = PIMADDR_ANY;
/* Assert state */
ch->t_ifassert_timer = NULL;
@@ -688,8 +686,8 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
struct pim_rpf rpf;
rpf.source_nexthop.interface = ifp;
- rpf.rpf_addr.u.prefix4 =
- pim_ifp->primary_address;
+ pim_addr_to_prefix(&rpf.rpf_addr,
+ pim_ifp->primary_address);
pim_jp_agg_single_upstream_send(
&rpf, ch->upstream, 0);
}
@@ -733,11 +731,12 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
}
static void check_recv_upstream(int is_join, struct interface *recv_ifp,
- struct in_addr upstream, pim_sgaddr *sg,
+ pim_addr upstream, pim_sgaddr *sg,
uint8_t source_flags, int holdtime)
{
struct pim_upstream *up;
struct pim_interface *pim_ifp = recv_ifp->info;
+ pim_addr rpf_addr;
/* Upstream (S,G) in Joined state ? */
up = pim_upstream_find(pim_ifp->pim, sg);
@@ -755,16 +754,13 @@ static void check_recv_upstream(int is_join, struct interface *recv_ifp,
return;
}
+ rpf_addr = pim_addr_from_prefix(&up->rpf.rpf_addr);
+
/* upstream directed to RPF'(S,G) ? */
- if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) {
- char up_str[INET_ADDRSTRLEN];
- char rpf_str[PREFIX_STRLEN];
- pim_inet4_dump("<up?>", upstream, up_str, sizeof(up_str));
- pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str,
- sizeof(rpf_str));
+ if (pim_addr_cmp(upstream, rpf_addr)) {
zlog_warn(
- "%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s",
- __FILE__, __func__, up->sg_str, up_str, rpf_str,
+ "%s %s: (S,G)=%s upstream=%pPAs not directed to RPF'(S,G)=%pPAs on interface %s",
+ __FILE__, __func__, up->sg_str, &upstream, &rpf_addr,
recv_ifp->name);
return;
}
@@ -798,7 +794,7 @@ static void check_recv_upstream(int is_join, struct interface *recv_ifp,
}
static int nonlocal_upstream(int is_join, struct interface *recv_ifp,
- struct in_addr upstream, pim_sgaddr *sg,
+ pim_addr upstream, pim_sgaddr *sg,
uint8_t source_flags, uint16_t holdtime)
{
struct pim_interface *recv_pim_ifp;
@@ -807,18 +803,16 @@ static int nonlocal_upstream(int is_join, struct interface *recv_ifp,
recv_pim_ifp = recv_ifp->info;
assert(recv_pim_ifp);
- is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr);
+ is_local = !pim_addr_cmp(upstream, recv_pim_ifp->primary_address);
if (is_local)
return 0;
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
- char up_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
- zlog_warn("%s: recv %s (S,G)=%pSG to non-local upstream=%s on %s",
- __func__, is_join ? "join" : "prune",
- sg, up_str, recv_ifp->name);
- }
+ if (PIM_DEBUG_PIM_TRACE_DETAIL)
+ zlog_warn(
+ "%s: recv %s (S,G)=%pSG to non-local upstream=%pPAs on %s",
+ __func__, is_join ? "join" : "prune", sg, &upstream,
+ recv_ifp->name);
/*
* Since recv upstream addr was not directed to our primary
@@ -851,8 +845,8 @@ static void pim_ifchannel_ifjoin_handler(struct pim_ifchannel *ch,
}
-void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
- struct in_addr upstream, pim_sgaddr *sg,
+void pim_ifchannel_join_add(struct interface *ifp, pim_addr neigh_addr,
+ pim_addr upstream, pim_sgaddr *sg,
uint8_t source_flags, uint16_t holdtime)
{
struct pim_interface *pim_ifp;
@@ -883,11 +877,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
address of the join message is our primary address.
*/
if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
- char neigh_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<neigh?>", neigh_addr, neigh_str,
- sizeof(neigh_str));
- zlog_warn("%s: Assert Loser recv Join%s from %s on %s",
- __func__, ch->sg_str, neigh_str, ifp->name);
+ zlog_warn("%s: Assert Loser recv Join%s from %pI4 on %s",
+ __func__, ch->sg_str, &neigh_addr, ifp->name);
assert_action_a5(ch);
}
@@ -1016,7 +1007,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
}
}
-void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
+void pim_ifchannel_prune(struct interface *ifp, pim_addr upstream,
pim_sgaddr *sg, uint8_t source_flags,
uint16_t holdtime)
{
@@ -1235,10 +1226,8 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, pim_sgaddr *sg,
struct prefix_list *plist = prefix_list_lookup(
AFI_IP, pim->spt.plist);
struct prefix g;
- g.family = AF_INET;
- g.prefixlen = IPV4_MAX_BITLEN;
- g.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&g, up->sg.grp);
if (prefix_list_apply(plist, &g)
== PREFIX_DENY) {
pim_channel_add_oif(
@@ -1368,23 +1357,17 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch)
if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric))
return;
- if (PIM_DEBUG_PIM_EVENTS) {
- char old_addr_str[INET_ADDRSTRLEN];
- char new_addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<old_addr?>", ch->ifassert_my_metric.ip_address,
- old_addr_str, sizeof(old_addr_str));
- pim_inet4_dump("<new_addr?>", my_metric_new.ip_address,
- new_addr_str, sizeof(new_addr_str));
+ if (PIM_DEBUG_PIM_EVENTS)
zlog_debug(
- "%s: my_assert_metric(%pPAs,%pPAs,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s",
+ "%s: my_assert_metric(%pPAs,%pPAs,%s) changed from %u,%u,%u,%pPAs to %u,%u,%u,%pPAs",
__func__, &ch->sg.src, &ch->sg.grp, ch->interface->name,
ch->ifassert_my_metric.rpt_bit_flag,
ch->ifassert_my_metric.metric_preference,
- ch->ifassert_my_metric.route_metric, old_addr_str,
+ ch->ifassert_my_metric.route_metric,
+ &ch->ifassert_my_metric.ip_address,
my_metric_new.rpt_bit_flag,
my_metric_new.metric_preference,
- my_metric_new.route_metric, new_addr_str);
- }
+ my_metric_new.route_metric, &my_metric_new.ip_address);
ch->ifassert_my_metric = my_metric_new;
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index ab405202e3..0c5b6780d1 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -126,10 +126,10 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp);
struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, pim_sgaddr *sg);
struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg,
uint8_t ch_flags, int up_flags);
-void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
- struct in_addr upstream, pim_sgaddr *sg,
+void pim_ifchannel_join_add(struct interface *ifp, pim_addr neigh_addr,
+ pim_addr upstream, pim_sgaddr *sg,
uint8_t source_flags, uint16_t holdtime);
-void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
+void pim_ifchannel_prune(struct interface *ifp, pim_addr upstream,
pim_sgaddr *sg, uint8_t source_flags,
uint16_t holdtime);
int pim_ifchannel_local_membership_add(struct interface *ifp, pim_sgaddr *sg,
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index fa2d8d462b..51a3ceee15 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -54,23 +54,17 @@ static void on_trace(const char *label, struct interface *ifp,
}
static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
- uint16_t holdtime, struct in_addr upstream,
- pim_sgaddr *sg, uint8_t source_flags)
+ uint16_t holdtime, pim_addr upstream, pim_sgaddr *sg,
+ uint8_t source_flags)
{
struct pim_interface *pim_ifp = NULL;
- if (PIM_DEBUG_PIM_TRACE) {
- char up_str[INET_ADDRSTRLEN];
- char neigh_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
- pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str,
- sizeof(neigh_str));
- zlog_debug("%s: join (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
- __func__, sg,
- !!(source_flags & PIM_RPT_BIT_MASK),
- !!(source_flags & PIM_WILDCARD_BIT_MASK), up_str,
- holdtime, neigh_str, ifp->name);
- }
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug(
+ "%s: join (S,G)=%pSG rpt=%d wc=%d upstream=%pPAs holdtime=%d from %pPA on %s",
+ __func__, sg, !!(source_flags & PIM_RPT_BIT_MASK),
+ !!(source_flags & PIM_WILDCARD_BIT_MASK), &upstream,
+ holdtime, &neigh->source_addr, ifp->name);
pim_ifp = ifp->info;
assert(pim_ifp);
@@ -84,6 +78,7 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
if ((source_flags & PIM_RPT_BIT_MASK)
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp);
+ pim_addr rpf_addr;
if (!rp) {
zlog_warn("%s: Lookup of RP failed for %pSG", __func__,
@@ -94,13 +89,11 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
* If the RP sent in the message is not
* our RP for the group, drop the message
*/
- if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) {
- char local_rp[INET_ADDRSTRLEN];
- pim_inet4_dump("<local?>", rp->rpf_addr.u.prefix4,
- local_rp, sizeof(local_rp));
+ rpf_addr = pim_addr_from_prefix(&rp->rpf_addr);
+ if (pim_addr_cmp(sg->src, rpf_addr)) {
zlog_warn(
- "%s: Specified RP(%pPAs) in join is different than our configured RP(%s)",
- __func__, &sg->src, local_rp);
+ "%s: Specified RP(%pPAs) in join is different than our configured RP(%pPAs)",
+ __func__, &sg->src, &rpf_addr);
return;
}
@@ -120,24 +113,17 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
}
static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh,
- uint16_t holdtime, struct in_addr upstream,
- pim_sgaddr *sg, uint8_t source_flags)
+ uint16_t holdtime, pim_addr upstream, pim_sgaddr *sg,
+ uint8_t source_flags)
{
struct pim_interface *pim_ifp = NULL;
- if (PIM_DEBUG_PIM_TRACE) {
- char up_str[INET_ADDRSTRLEN];
- char neigh_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
- pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str,
- sizeof(neigh_str));
- zlog_debug("%s: prune (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
- __func__, sg,
- source_flags & PIM_RPT_BIT_MASK,
- source_flags & PIM_WILDCARD_BIT_MASK, up_str,
- holdtime,
- neigh_str, ifp->name);
- }
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug(
+ "%s: prune (S,G)=%pSG rpt=%d wc=%d upstream=%pPAs holdtime=%d from %pPA on %s",
+ __func__, sg, source_flags & PIM_RPT_BIT_MASK,
+ source_flags & PIM_WILDCARD_BIT_MASK, &upstream,
+ holdtime, &neigh->source_addr, ifp->name);
pim_ifp = ifp->info;
assert(pim_ifp);
@@ -165,7 +151,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
struct in_addr src_addr, uint8_t *tlv_buf,
int tlv_buf_size)
{
- struct prefix msg_upstream_addr;
+ pim_addr msg_upstream_addr;
+ bool wrong_af = false;
struct pim_interface *pim_ifp;
uint8_t msg_num_groups;
uint16_t msg_holdtime;
@@ -184,8 +171,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Parse ucast addr
*/
- addr_offset =
- pim_parse_addr_ucast(&msg_upstream_addr, buf, pastend - buf);
+ addr_offset = pim_parse_addr_ucast(&msg_upstream_addr, buf,
+ pastend - buf, &wrong_af);
if (addr_offset < 1) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
@@ -198,12 +185,12 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Check upstream address family
*/
- if (msg_upstream_addr.family != AF_INET) {
+ if (wrong_af) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
zlog_warn(
- "%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s",
- __func__, msg_upstream_addr.family, src_str, ifp->name);
+ "%s: ignoring join/prune directed to unexpected addr family from %s on %s",
+ __func__, src_str, ifp->name);
return -2;
}
@@ -226,14 +213,11 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (PIM_DEBUG_PIM_J_P) {
char src_str[INET_ADDRSTRLEN];
- char upstream_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
- upstream_str, sizeof(upstream_str));
zlog_debug(
- "%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s",
- __func__, upstream_str, msg_num_groups, msg_holdtime,
- src_str, ifp->name);
+ "%s: join/prune upstream=%pPAs groups=%d holdtime=%d from %s on %s",
+ __func__, &msg_upstream_addr, msg_num_groups,
+ msg_holdtime, src_str, ifp->name);
}
/* Scan groups */
@@ -271,14 +255,11 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (PIM_DEBUG_PIM_J_P) {
char src_str[INET_ADDRSTRLEN];
- char upstream_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
- pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
- upstream_str, sizeof(upstream_str));
zlog_debug(
- "%s: join/prune upstream=%s group=%pPA/32 join_src=%d prune_src=%d from %s on %s",
- __func__, upstream_str, &sg.grp,
+ "%s: join/prune upstream=%pPAs group=%pPA/32 join_src=%d prune_src=%d from %s on %s",
+ __func__, &msg_upstream_addr, &sg.grp,
msg_num_joined_sources, msg_num_pruned_sources,
src_str, ifp->name);
}
@@ -300,9 +281,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (filtered)
continue;
- recv_join(ifp, neigh, msg_holdtime,
- msg_upstream_addr.u.prefix4, &sg,
- msg_source_flags);
+ recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr,
+ &sg, msg_source_flags);
if (pim_addr_is_any(sg.src)) {
starg_ch = pim_ifchannel_find(ifp, &sg);
@@ -326,9 +306,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (filtered)
continue;
- recv_prune(ifp, neigh, msg_holdtime,
- msg_upstream_addr.u.prefix4, &sg,
- msg_source_flags);
+ recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr,
+ &sg, msg_source_flags);
/*
* So if we are receiving a S,G,RPT prune
* before we have any data for that S,G
@@ -516,7 +495,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
grp = &msg->groups[0];
curr_ptr = (uint8_t *)grp;
packet_size = sizeof(struct pim_msg_header);
- packet_size += sizeof(struct pim_encoded_ipv4_unicast);
+ packet_size += sizeof(pim_encoded_unicast);
packet_size +=
4; // reserved (1) + groups (1) + holdtime (2)
@@ -525,14 +504,11 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
}
if (PIM_DEBUG_PIM_J_P) {
char dst_str[INET_ADDRSTRLEN];
- char grp_str[INET_ADDRSTRLEN];
pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4,
dst_str, sizeof(dst_str));
- pim_inet4_dump("<grp?>", group->group, grp_str,
- sizeof(grp_str));
zlog_debug(
- "%s: sending (G)=%s to upstream=%s on interface %s",
- __func__, grp_str, dst_str,
+ "%s: sending (G)=%pPAs to upstream=%s on interface %s",
+ __func__, &group->group, dst_str,
rpf->source_nexthop.interface->name);
}
@@ -564,7 +540,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
grp = &msg->groups[0];
curr_ptr = (uint8_t *)grp;
packet_size = sizeof(struct pim_msg_header);
- packet_size += sizeof(struct pim_encoded_ipv4_unicast);
+ packet_size += sizeof(pim_encoded_unicast);
packet_size +=
4; // reserved (1) + groups (1) + holdtime (2)
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index feeef15f81..42ad5dcd1e 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -60,13 +60,7 @@ int pim_jp_agg_group_list_cmp(void *arg1, void *arg2)
const struct pim_jp_agg_group *jag2 =
(const struct pim_jp_agg_group *)arg2;
- if (jag1->group.s_addr < jag2->group.s_addr)
- return -1;
-
- if (jag1->group.s_addr > jag2->group.s_addr)
- return 1;
-
- return 0;
+ return pim_addr_cmp(jag1->group, jag2->group);
}
static int pim_jp_agg_src_cmp(void *arg1, void *arg2)
@@ -163,17 +157,10 @@ void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up,
}
if (nbr) {
- if (PIM_DEBUG_TRACE) {
- char src_str[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<src?>", nbr->source_addr, src_str,
- sizeof(src_str));
- zlog_debug(
- "up %s remove from nbr %s/%s jp-agg-list",
- up->sg_str,
- nbr->interface->name,
- src_str);
- }
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("up %s remove from nbr %s/%pPAs jp-agg-list",
+ up->sg_str, nbr->interface->name,
+ &nbr->source_addr);
}
if (js) {
@@ -290,17 +277,11 @@ void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up,
}
if (nbr) {
- if (PIM_DEBUG_TRACE) {
- char src_str[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<src?>", nbr->source_addr, src_str,
- sizeof(src_str));
- zlog_debug(
- "up %s add to nbr %s/%s jp-agg-list",
- up->sg_str,
- up->rpf.source_nexthop.interface->name,
- src_str);
- }
+ if (PIM_DEBUG_TRACE)
+ zlog_debug("up %s add to nbr %s/%pPAs jp-agg-list",
+ up->sg_str,
+ up->rpf.source_nexthop.interface->name,
+ &nbr->source_addr);
}
if (!js) {
diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c
index aa41033cea..0896c52a75 100644
--- a/pimd/pim_macro.c
+++ b/pimd/pim_macro.c
@@ -132,7 +132,7 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch)
return 0; /* false */
/* AssertWinner(S,G,I) == me ? */
- if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr)
+ if (!pim_addr_cmp(ch->ifassert_winner, pim_ifp->primary_address))
return 0; /* false */
spt_assert_metric = pim_macro_spt_assert_metric(
@@ -170,7 +170,7 @@ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch)
return 0; /* false */
/* OR AssertWinner(S,G,I) == me ? */
- if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr)
+ if (!pim_addr_cmp(ch->ifassert_winner, pim_ifp->primary_address))
return 1; /* true */
/*
@@ -412,8 +412,8 @@ int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch)
return 1; /* true */
/* AssertWinner(S,G,I) == me ? */
- if (ch->ifassert_winner.s_addr
- == pim_ifp->primary_address.s_addr)
+ if (!pim_addr_cmp(ch->ifassert_winner,
+ pim_ifp->primary_address))
return 1; /* true */
}
diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c
index c493ded0c6..e25cf11549 100644
--- a/pimd/pim_msg.c
+++ b/pimd/pim_msg.c
@@ -97,6 +97,68 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr,
return buf + PIM_ENCODED_IPV4_SOURCE_SIZE;
}
+uint8_t *pim_msg_addr_encode_ipv6_source(uint8_t *buf, struct in6_addr addr,
+ uint8_t bits)
+{
+ buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV6; /* addr family */
+ buf[1] = '\0'; /* native encoding */
+ buf[2] = bits;
+ buf[3] = 128; /* mask len */
+ buf += 4;
+
+ memcpy(buf, &addr, sizeof(addr));
+ buf += sizeof(addr);
+
+ return buf;
+}
+
+uint8_t *pim_msg_addr_encode_ipv6_ucast(uint8_t *buf, struct in6_addr addr)
+{
+ buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV6; /* addr family */
+ buf[1] = '\0'; /* native encoding */
+ buf += 2;
+
+ memcpy(buf, &addr, sizeof(addr));
+ buf += sizeof(addr);
+
+ return buf;
+}
+
+uint8_t *pim_msg_addr_encode_ipv6_group(uint8_t *buf, struct in6_addr addr)
+{
+ buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV6; /* addr family */
+ buf[1] = '\0'; /* native encoding */
+ buf[2] = '\0'; /* reserved */
+ buf[3] = 128; /* mask len */
+ buf += 4;
+
+ memcpy(buf, &addr, sizeof(addr));
+ buf += sizeof(addr);
+
+ return buf;
+}
+
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
+#define pim_msg_addr_encode(what) pim_msg_addr_encode_ipv4_##what
+#else
+#define pim_msg_addr_encode(what) pim_msg_addr_encode_ipv6_##what
+#endif
+
+uint8_t *pim_msg_addr_encode_ucast(uint8_t *buf, pim_addr addr)
+{
+ return pim_msg_addr_encode(ucast)(buf, addr);
+}
+
+uint8_t *pim_msg_addr_encode_group(uint8_t *buf, pim_addr addr)
+{
+ return pim_msg_addr_encode(group)(buf, addr);
+}
+
+uint8_t *pim_msg_addr_encode_source(uint8_t *buf, pim_addr addr, uint8_t bits)
+{
+ return pim_msg_addr_encode(source)(buf, addr, bits);
+}
+
/*
* For the given 'struct pim_jp_sources' list
* determine the size_t it would take up.
@@ -109,10 +171,10 @@ size_t pim_msg_get_jp_group_size(struct list *sources)
if (!sources)
return 0;
- size += sizeof(struct pim_encoded_group_ipv4);
+ size += sizeof(pim_encoded_group);
size += 4; // Joined sources (2) + Pruned Sources (2)
- size += sizeof(struct pim_encoded_source_ipv4) * sources->count;
+ size += sizeof(pim_encoded_source) * sources->count;
js = listgetdata(listhead(sources));
if (js && pim_addr_is_any(js->up->sg.src) && js->is_join) {
@@ -137,8 +199,7 @@ size_t pim_msg_get_jp_group_size(struct list *sources)
if (child->rpf.source_nexthop.interface &&
!pim_rpf_is_same(&up->rpf,
&child->rpf)) {
- size += sizeof(
- struct pim_encoded_source_ipv4);
+ size += sizeof(pim_encoded_source);
PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(
child->flags);
if (PIM_DEBUG_PIM_PACKETS)
@@ -156,8 +217,7 @@ size_t pim_msg_get_jp_group_size(struct list *sources)
* but it's inherited OIL is empty. So just
* prune it off.
*/
- size += sizeof(
- struct pim_encoded_source_ipv4);
+ size += sizeof(pim_encoded_source);
PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(
child->flags);
if (PIM_DEBUG_PIM_PACKETS)
@@ -179,12 +239,12 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
struct listnode *node, *nnode;
struct pim_jp_sources *source;
struct pim_upstream *up = NULL;
- struct in_addr stosend;
+ pim_addr stosend;
uint8_t bits;
uint8_t tgroups = 0;
memset(grp, 0, size);
- pim_msg_addr_encode_ipv4_group((uint8_t *)&grp->g, sgs->group);
+ pim_msg_addr_encode_group((uint8_t *)&grp->g, sgs->group);
for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) {
/* number of joined/pruned sources */
@@ -198,7 +258,7 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
struct pim_rpf *rpf = pim_rp_g(pim, source->up->sg.grp);
bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT
| PIM_ENCODE_RPT_BIT;
- stosend = rpf->rpf_addr.u.prefix4;
+ stosend = pim_addr_from_prefix(&rpf->rpf_addr);
/* Only Send SGRpt in case of *,G Join */
if (source->is_join)
up = source->up;
@@ -207,8 +267,8 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
stosend = source->up->sg.src;
}
- pim_msg_addr_encode_ipv4_source((uint8_t *)&grp->s[tgroups],
- stosend, bits);
+ pim_msg_addr_encode_source((uint8_t *)&grp->s[tgroups], stosend,
+ bits);
tgroups++;
}
@@ -218,11 +278,11 @@ size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) {
if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(
child->flags)) {
- pim_msg_addr_encode_ipv4_source(
+ pim_msg_addr_encode_source(
(uint8_t *)&grp->s[tgroups],
child->sg.src,
- PIM_ENCODE_SPARSE_BIT
- | PIM_ENCODE_RPT_BIT);
+ PIM_ENCODE_SPARSE_BIT |
+ PIM_ENCODE_RPT_BIT);
tgroups++;
PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(
child->flags);
diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h
index 2d69a4b03a..522e94504a 100644
--- a/pimd/pim_msg.h
+++ b/pimd/pim_msg.h
@@ -75,6 +75,12 @@ struct pim_encoded_ipv4_unicast {
struct in_addr addr;
} __attribute__((packed));
+struct pim_encoded_ipv6_unicast {
+ uint8_t family;
+ uint8_t reserved;
+ struct in6_addr addr;
+} __attribute__((packed));
+
/*
* Encoded Group format. RFC 4601 Sec 4.9.1
* 0 1 2 3
@@ -103,6 +109,23 @@ struct pim_encoded_group_ipv4 {
struct in_addr addr;
} __attribute__((packed));
+struct pim_encoded_group_ipv6 {
+ uint8_t family;
+ uint8_t ne;
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+ uint8_t sz : 1; /* scope zone bit */
+ uint8_t reserved : 6; /* Reserved */
+ uint8_t bidir : 1; /* Bidir bit */
+#elif (BYTE_ORDER == BIG_ENDIAN)
+ uint8_t bidir : 1; /* Bidir bit */
+ uint8_t reserved : 6; /* Reserved */
+ uint8_t sz : 1; /* scope zone bit */
+#else
+#error "Please set byte order"
+#endif
+ uint8_t mask;
+ struct in6_addr addr;
+} __attribute__((packed));
/*
* Encoded Source format. RFC 4601 Sec 4.9.1
@@ -122,16 +145,36 @@ struct pim_encoded_source_ipv4 {
struct in_addr addr;
} __attribute__((packed));
+struct pim_encoded_source_ipv6 {
+ uint8_t family;
+ uint8_t ne;
+ uint8_t bits;
+ uint8_t mask;
+ struct in6_addr addr;
+} __attribute__((packed));
+
+/* clang-format off */
+#if PIM_IPV == 4
+typedef struct pim_encoded_ipv4_unicast pim_encoded_unicast;
+typedef struct pim_encoded_group_ipv4 pim_encoded_group;
+typedef struct pim_encoded_source_ipv4 pim_encoded_source;
+#else
+typedef struct pim_encoded_ipv6_unicast pim_encoded_unicast;
+typedef struct pim_encoded_group_ipv6 pim_encoded_group;
+typedef struct pim_encoded_source_ipv6 pim_encoded_source;
+#endif
+/* clang-format on */
+
struct pim_jp_groups {
- struct pim_encoded_group_ipv4 g;
+ pim_encoded_group g;
uint16_t joins;
uint16_t prunes;
- struct pim_encoded_source_ipv4 s[1];
+ pim_encoded_source s[1];
} __attribute__((packed));
struct pim_jp {
struct pim_msg_header header;
- struct pim_encoded_ipv4_unicast addr;
+ pim_encoded_unicast addr;
uint8_t reserved;
uint8_t num_groups;
uint16_t holdtime;
@@ -149,6 +192,14 @@ uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr);
uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr,
uint8_t bits);
+uint8_t *pim_msg_addr_encode_ipv6_ucast(uint8_t *buf, struct in6_addr addr);
+uint8_t *pim_msg_addr_encode_ipv6_group(uint8_t *buf, struct in6_addr addr);
+uint8_t *pim_msg_addr_encode_ipv6_source(uint8_t *buf, struct in6_addr addr,
+ uint8_t bits);
+
+uint8_t *pim_msg_addr_encode_ucast(uint8_t *buf, pim_addr addr);
+uint8_t *pim_msg_addr_encode_group(uint8_t *buf, pim_addr addr);
+uint8_t *pim_msg_addr_encode_source(uint8_t *buf, pim_addr addr, uint8_t bits);
size_t pim_msg_get_jp_group_size(struct list *sources);
size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp,
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 530c2e429b..6e3d2739e7 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -58,10 +58,8 @@ static void dr_election_by_addr(struct interface *ifp)
}
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
- if (ntohl(neigh->source_addr.s_addr)
- > ntohl(pim_ifp->pim_dr_addr.s_addr)) {
+ if (pim_addr_cmp(neigh->source_addr, pim_ifp->pim_dr_addr) > 0)
pim_ifp->pim_dr_addr = neigh->source_addr;
- }
}
}
@@ -85,15 +83,14 @@ static void dr_election_by_pri(struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
if (PIM_DEBUG_PIM_TRACE) {
- zlog_info("%s: neigh pri %u addr %x if dr addr %x",
+ zlog_info("%s: neigh pri %u addr %pPA if dr addr %pPA",
__func__, neigh->dr_priority,
- ntohl(neigh->source_addr.s_addr),
- ntohl(pim_ifp->pim_dr_addr.s_addr));
+ &neigh->source_addr, &pim_ifp->pim_dr_addr);
}
- if ((neigh->dr_priority > dr_pri)
- || ((neigh->dr_priority == dr_pri)
- && (ntohl(neigh->source_addr.s_addr)
- > ntohl(pim_ifp->pim_dr_addr.s_addr)))) {
+ if ((neigh->dr_priority > dr_pri) ||
+ ((neigh->dr_priority == dr_pri) &&
+ (pim_addr_cmp(neigh->source_addr, pim_ifp->pim_dr_addr) >
+ 0))) {
pim_ifp->pim_dr_addr = neigh->source_addr;
dr_pri = neigh->dr_priority;
}
@@ -110,7 +107,7 @@ static void dr_election_by_pri(struct interface *ifp)
int pim_if_dr_election(struct interface *ifp)
{
struct pim_interface *pim_ifp = ifp->info;
- struct in_addr old_dr_addr;
+ pim_addr old_dr_addr;
++pim_ifp->pim_dr_election_count;
@@ -123,18 +120,13 @@ int pim_if_dr_election(struct interface *ifp)
}
/* DR changed ? */
- if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
-
- if (PIM_DEBUG_PIM_EVENTS) {
- char dr_old_str[INET_ADDRSTRLEN];
- char dr_new_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str,
- sizeof(dr_old_str));
- pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr,
- dr_new_str, sizeof(dr_new_str));
- zlog_debug("%s: DR was %s now is %s on interface %s",
- __func__, dr_old_str, dr_new_str, ifp->name);
- }
+ if (pim_addr_cmp(old_dr_addr, pim_ifp->pim_dr_addr)) {
+
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug(
+ "%s: DR was %pPA now is %pPA on interface %s",
+ __func__, &old_dr_addr, &pim_ifp->pim_dr_addr,
+ ifp->name);
pim_ifp->pim_dr_election_last =
pim_time_monotonic_sec(); /* timestamp */
@@ -218,14 +210,10 @@ static int on_neighbor_timer(struct thread *t)
ifp = neigh->interface;
- if (PIM_DEBUG_PIM_TRACE) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", neigh->source_addr, src_str,
- sizeof(src_str));
+ if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
- "Expired %d sec holdtime for neighbor %s on interface %s",
- neigh->holdtime, src_str, ifp->name);
- }
+ "Expired %d sec holdtime for neighbor %pPA on interface %s",
+ neigh->holdtime, &neigh->source_addr, ifp->name);
snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
pim_neighbor_delete(ifp, neigh, msg);
@@ -255,14 +243,10 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
return;
}
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", neigh->source_addr, src_str,
- sizeof(src_str));
- zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
- __func__, neigh->holdtime, src_str,
+ if (PIM_DEBUG_PIM_TRACE_DETAIL)
+ zlog_debug("%s: starting %u sec timer for neighbor %pPA on %s",
+ __func__, neigh->holdtime, &neigh->source_addr,
neigh->interface->name);
- }
thread_add_timer(router->master, on_neighbor_timer, neigh,
neigh->holdtime, &neigh->t_expire_timer);
@@ -273,17 +257,14 @@ static int on_neighbor_jp_timer(struct thread *t)
struct pim_neighbor *neigh = THREAD_ARG(t);
struct pim_rpf rpf;
- if (PIM_DEBUG_PIM_TRACE) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", neigh->source_addr, src_str,
- sizeof(src_str));
- zlog_debug("%s:Sending JP Agg to %s on %s with %d groups",
- __func__, src_str, neigh->interface->name,
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug("%s:Sending JP Agg to %pPA on %s with %d groups",
+ __func__, &neigh->source_addr,
+ neigh->interface->name,
neigh->upstream_jp_agg->count);
- }
rpf.source_nexthop.interface = neigh->interface;
- rpf.rpf_addr.u.prefix4 = neigh->source_addr;
+ pim_addr_to_prefix(&rpf.rpf_addr, neigh->source_addr);
pim_joinprune_send(&rpf, neigh->upstream_jp_agg);
thread_add_timer(router->master, on_neighbor_jp_timer, neigh,
@@ -300,7 +281,7 @@ static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh)
}
static struct pim_neighbor *
-pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
+pim_neighbor_new(struct interface *ifp, pim_addr source_addr,
pim_hello_options hello_options, uint16_t holdtime,
uint16_t propagation_delay, uint16_t override_interval,
uint32_t dr_priority, uint32_t generation_id,
@@ -308,7 +289,6 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
{
struct pim_interface *pim_ifp;
struct pim_neighbor *neigh;
- char src_str[INET_ADDRSTRLEN];
assert(ifp);
pim_ifp = ifp->info;
@@ -343,15 +323,12 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
*/
PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp->flags);
- pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str));
-
- if (PIM_DEBUG_PIM_EVENTS) {
- zlog_debug("%s: creating PIM neighbor %s on interface %s",
- __func__, src_str, ifp->name);
- }
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug("%s: creating PIM neighbor %pPA on interface %s",
+ __func__, &source_addr, ifp->name);
- zlog_notice("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str,
- ifp->name);
+ zlog_notice("PIM NEIGHBOR UP: neighbor %pPA on interface %s",
+ &source_addr, ifp->name);
if (neigh->propagation_delay_msec
> pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
@@ -448,7 +425,7 @@ struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
}
struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
- struct in_addr source_addr)
+ pim_addr source_addr)
{
struct pim_interface *pim_ifp;
struct listnode *node;
@@ -462,7 +439,7 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
return NULL;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
- if (source_addr.s_addr == neigh->source_addr.s_addr) {
+ if (!pim_addr_cmp(source_addr, neigh->source_addr)) {
return neigh;
}
}
@@ -470,6 +447,15 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
return NULL;
}
+struct pim_neighbor *pim_neighbor_find_prefix(struct interface *ifp,
+ const struct prefix *src_prefix)
+{
+ pim_addr addr;
+
+ addr = pim_addr_from_prefix(src_prefix);
+ return pim_neighbor_find(ifp, addr);
+}
+
/*
* Find the *one* interface out
* this interface. If more than
@@ -486,7 +472,7 @@ struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp)
}
struct pim_neighbor *
-pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
+pim_neighbor_add(struct interface *ifp, pim_addr source_addr,
pim_hello_options hello_options, uint16_t holdtime,
uint16_t propagation_delay, uint16_t override_interval,
uint32_t dr_priority, uint32_t generation_id,
@@ -507,11 +493,8 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
listnode_add(pim_ifp->pim_neighbor_list, neigh);
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
- char str[INET_ADDRSTRLEN];
- pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof(str));
- zlog_debug("%s: neighbor %s added ", __func__, str);
- }
+ if (PIM_DEBUG_PIM_TRACE_DETAIL)
+ zlog_debug("%s: neighbor %pPA added ", __func__, &source_addr);
/*
RFC 4601: 4.3.2. DR Election
@@ -610,14 +593,12 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
const char *delete_message)
{
struct pim_interface *pim_ifp;
- char src_str[INET_ADDRSTRLEN];
pim_ifp = ifp->info;
assert(pim_ifp);
- pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
- zlog_notice("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
- src_str, ifp->name, delete_message);
+ zlog_notice("PIM NEIGHBOR DOWN: neighbor %pPA on interface %s: %s",
+ &neigh->source_addr, ifp->name, delete_message);
THREAD_OFF(neigh->t_expire_timer);
@@ -664,8 +645,8 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
}
if (PIM_DEBUG_PIM_TRACE) {
- zlog_debug("%s: deleting PIM neighbor %s on interface %s",
- __func__, src_str, ifp->name);
+ zlog_debug("%s: deleting PIM neighbor %pPA on interface %s",
+ __func__, &neigh->source_addr, ifp->name);
}
listnode_delete(pim_ifp->pim_neighbor_list, neigh);
@@ -720,8 +701,7 @@ struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
administrator in a rate-limited manner.
*/
static void delete_from_neigh_addr(struct interface *ifp,
- struct list *addr_list,
- struct in_addr neigh_addr)
+ struct list *addr_list, pim_addr neigh_addr)
{
struct listnode *addr_node;
struct prefix *addr;
@@ -752,24 +732,15 @@ static void delete_from_neigh_addr(struct interface *ifp,
neigh, addr);
if (p) {
char addr_str[INET_ADDRSTRLEN];
- char this_neigh_str[INET_ADDRSTRLEN];
- char other_neigh_str[INET_ADDRSTRLEN];
pim_inet4_dump(
"<addr?>", addr->u.prefix4,
addr_str, sizeof(addr_str));
- pim_inet4_dump("<neigh1?>", neigh_addr,
- this_neigh_str,
- sizeof(this_neigh_str));
- pim_inet4_dump("<neigh2?>",
- neigh->source_addr,
- other_neigh_str,
- sizeof(other_neigh_str));
zlog_info(
- "secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
- addr_str, this_neigh_str,
- other_neigh_str, ifp->name);
+ "secondary addr %s recvd from neigh %pPA deleted from neigh %pPA on %s",
+ addr_str, &neigh_addr,
+ &neigh->source_addr, ifp->name);
listnode_delete(neigh->prefix_list, p);
prefix_free(&p);
diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h
index 12c469ae2a..2673d22480 100644
--- a/pimd/pim_neighbor.h
+++ b/pimd/pim_neighbor.h
@@ -51,7 +51,9 @@ struct pim_neighbor {
void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);
void pim_neighbor_free(struct pim_neighbor *neigh);
struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
- struct in_addr source_addr);
+ pim_addr source_addr);
+struct pim_neighbor *pim_neighbor_find_prefix(struct interface *ifp,
+ const struct prefix *src_prefix);
struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
struct prefix *src);
struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp);
@@ -60,7 +62,7 @@ struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp);
#define PIM_NEIGHBOR_SEND_DELAY 0
#define PIM_NEIGHBOR_SEND_NOW 1
struct pim_neighbor *
-pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
+pim_neighbor_add(struct interface *ifp, pim_addr source_addr,
pim_hello_options hello_options, uint16_t holdtime,
uint16_t propagation_delay, uint16_t override_interval,
uint32_t dr_priority, uint32_t generation_id,
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 26ca48543f..beaa5c802b 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -237,10 +237,7 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
if (!pim_addr_is_any(upstream->sg.src))
continue;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = upstream->sg.grp;
-
+ pim_addr_to_prefix(&grp, upstream->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
if (trp_info == rp)
hash_release(pnc->upstream_hash, upstream);
@@ -338,8 +335,7 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr_addr,
if (if_is_loopback(ifp) && if_is_loopback(src_ifp))
return true;
- nbr = pim_neighbor_find(ifp,
- znh->nexthop_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(ifp, &znh->nexthop_addr);
if (!nbr)
continue;
@@ -362,9 +358,10 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr_addr,
*/
for (nh = pnc->nexthop; nh; nh = nh->next) {
- struct in_addr nhaddr;
+ pim_addr nhaddr;
switch (nh->type) {
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
case NEXTHOP_TYPE_IPV4:
if (nh->ifindex == IFINDEX_INTERNAL)
continue;
@@ -373,7 +370,16 @@ bool pim_nht_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr_addr,
case NEXTHOP_TYPE_IPV4_IFINDEX:
nhaddr = nh->gate.ipv4;
break;
+#else
+ case NEXTHOP_TYPE_IPV6:
+ if (nh->ifindex == IFINDEX_INTERNAL)
+ continue;
+ /* fallthru */
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ nhaddr = nh->gate.ipv6;
+ break;
+#endif
case NEXTHOP_TYPE_IFINDEX:
nhaddr = bsr_addr;
break;
@@ -550,9 +556,9 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
if (curr_route_valid
&& !pim_if_connected_to_source(nexthop->interface,
src->u.prefix4)) {
- nbr = pim_neighbor_find(
+ nbr = pim_neighbor_find_prefix(
nexthop->interface,
- nexthop->mrib_nexthop_addr.u.prefix4);
+ &nexthop->mrib_nexthop_addr);
if (!nbr
&& !if_is_loopback(nexthop->interface)) {
if (PIM_DEBUG_PIM_NHT)
@@ -599,8 +605,12 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
ifps[i] =
if_lookup_by_index(nh_node->ifindex, pim->vrf->vrf_id);
if (ifps[i]) {
- nbrs[i] = pim_neighbor_find(ifps[i],
- nh_node->gate.ipv4);
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
+ pim_addr nhaddr = nh_node->gate.ipv4;
+#else
+ pim_addr nhaddr = nh_node->gate.ipv6;
+#endif
+ nbrs[i] = pim_neighbor_find(ifps[i], nhaddr);
if (nbrs[i] || pim_if_connected_to_source(ifps[i],
src->u.prefix4))
@@ -789,7 +799,11 @@ int pim_parse_nexthop_update(ZAPI_CALLBACK_ARGS)
nbr = pim_neighbor_find_if(ifp1);
/* Overwrite with Nbr address as NH addr */
if (nbr)
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
nexthop->gate.ipv4 = nbr->source_addr;
+#else
+ nexthop->gate.ipv6 = nbr->source_addr;
+#endif
else {
// Mark nexthop address to 0 until PIM
// Nbr is resolved.
@@ -950,8 +964,8 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
ifps[i] = if_lookup_by_index(nexthop_tab[i].ifindex,
pim->vrf->vrf_id);
if (ifps[i]) {
- nbrs[i] = pim_neighbor_find(
- ifps[i], nexthop_tab[i].nexthop_addr.u.prefix4);
+ nbrs[i] = pim_neighbor_find_prefix(
+ ifps[i], &nexthop_tab[i].nexthop_addr);
if (nbrs[i]
|| pim_if_connected_to_source(ifps[i],
src->u.prefix4))
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index 2142d9010b..93ccfd78df 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -570,7 +570,7 @@ static int pim_msg_send_frame(int fd, char *buf, size_t len,
return 0;
}
-int pim_msg_send(int fd, pim_addr src, struct in_addr dst, uint8_t *pim_msg,
+int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
int pim_msg_size, const char *ifname)
{
struct sockaddr_in to;
diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h
index b9fdb14dc0..1931e8cee8 100644
--- a/pimd/pim_pim.h
+++ b/pimd/pim_pim.h
@@ -56,8 +56,8 @@ void pim_hello_restart_triggered(struct interface *ifp);
int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len);
-int pim_msg_send(int fd, struct in_addr src, struct in_addr dst,
- uint8_t *pim_msg, int pim_msg_size, const char *ifname);
+int pim_msg_send(int fd, pim_addr src, pim_addr dst, uint8_t *pim_msg,
+ int pim_msg_size, const char *ifname);
int pim_hello_send(struct interface *ifp, uint16_t holdtime);
#endif /* PIM_PIM_H */
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 855d912566..2cc80f957c 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -72,7 +72,6 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg,
unsigned int b1length = 0;
unsigned int length;
uint8_t *b1;
- struct prefix p;
if (PIM_DEBUG_PIM_REG) {
zlog_debug("Sending Register stop for %pSG to %pI4 on %s", sg,
@@ -86,10 +85,7 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg,
b1length += length;
b1 += length;
- p.family = AF_INET;
- p.u.prefix4 = sg->src;
- p.prefixlen = IPV4_MAX_BITLEN;
- length = pim_encode_addr_ucast(b1, &p);
+ length = pim_encode_addr_ucast(b1, sg->src);
b1length += length;
pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
@@ -117,8 +113,8 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
struct pim_interface *pim_ifp = ifp->info;
struct pim_instance *pim = pim_ifp->pim;
struct pim_upstream *upstream = NULL;
- struct prefix source;
pim_sgaddr sg;
+ bool wrong_af = false;
int l;
++pim_ifp->pim_ifstat_reg_stop_recv;
@@ -127,8 +123,12 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
l = pim_parse_addr_group(&sg, buf, buf_size);
buf += l;
buf_size -= l;
- pim_parse_addr_ucast(&source, buf, buf_size);
- sg.src = source.u.prefix4;
+ pim_parse_addr_ucast(&sg.src, buf, buf_size, &wrong_af);
+
+ if (wrong_af) {
+ zlog_err("invalid AF in Register-Stop on %s", ifp->name);
+ return 0;
+ }
upstream = pim_upstream_find(pim, &sg);
if (!upstream) {
@@ -399,11 +399,10 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
struct prefix_list *plist;
struct prefix src;
- plist = prefix_list_lookup(AFI_IP, pim->register_plist);
+ plist = prefix_list_lookup(PIM_AFI,
+ pim->register_plist);
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = sg.src;
+ pim_addr_to_prefix(&src, sg.src);
if (prefix_list_apply(plist, &src) == PREFIX_DENY) {
pim_register_stop_send(ifp, &sg, dest_addr,
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index f35adb0cea..a5183c9e9b 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -322,9 +322,11 @@ static int pim_rp_check_interface_addrs(struct rp_info *rp_info,
{
struct listnode *node;
struct pim_secondary_addr *sec_addr;
+ pim_addr rpf_addr;
- if (pim_ifp->primary_address.s_addr
- == rp_info->rp.rpf_addr.u.prefix4.s_addr)
+ rpf_addr = pim_addr_from_prefix(&rp_info->rp.rpf_addr);
+
+ if (!pim_addr_cmp(pim_ifp->primary_address, rpf_addr))
return 1;
if (!pim_ifp->sec_addr_list) {
@@ -362,8 +364,8 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
{
struct pim_rpf old_rpf;
enum pim_rpf_result rpf_result;
- struct in_addr old_upstream_addr;
- struct in_addr new_upstream_addr;
+ pim_addr old_upstream_addr;
+ pim_addr new_upstream_addr;
struct prefix nht_p;
old_upstream_addr = up->upstream_addr;
@@ -374,7 +376,7 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
zlog_debug("%s: pim upstream update for old upstream %pI4",
__func__, &old_upstream_addr);
- if (old_upstream_addr.s_addr == new_upstream_addr.s_addr)
+ if (!pim_addr_cmp(old_upstream_addr, new_upstream_addr))
return;
/* Lets consider a case, where a PIM upstream has a better RP as a
@@ -382,11 +384,9 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
* This upstream has to be added to the upstream hash of new RP's
* NHT(pnc) and has to be removed from old RP's NHT upstream hash
*/
- if (old_upstream_addr.s_addr != INADDR_ANY) {
+ if (!pim_addr_is_any(old_upstream_addr)) {
/* Deregister addr with Zebra NHT */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = old_upstream_addr;
+ pim_addr_to_prefix(&nht_p, old_upstream_addr);
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s: Deregister upstream %s addr %pFX with Zebra NHT",
@@ -536,14 +536,12 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
/* Find (*, G) upstream whose RP is not
* configured yet
*/
- if ((up->upstream_addr.s_addr == INADDR_ANY) &&
+ if (pim_addr_is_any(up->upstream_addr) &&
pim_addr_is_any(up->sg.src)) {
struct prefix grp;
struct rp_info *trp_info;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(
pim, &grp);
if (trp_info == rp_all) {
@@ -632,9 +630,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
struct prefix grp;
struct rp_info *trp_info;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
if (trp_info == rp_info) {
@@ -778,17 +774,18 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
/* Find the upstream (*, G) whose upstream address is
* same as the deleted RP
*/
- if ((up->upstream_addr.s_addr ==
- rp_info->rp.rpf_addr.u.prefix4.s_addr) &&
+ pim_addr rpf_addr;
+
+ rpf_addr = pim_addr_from_prefix(&rp_info->rp.rpf_addr);
+ if (!pim_addr_cmp(up->upstream_addr, rpf_addr) &&
pim_addr_is_any(up->sg.src)) {
struct prefix grp;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
+
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
if (trp_info == rp_all) {
pim_upstream_rpf_clear(pim, up);
- up->upstream_addr.s_addr = INADDR_ANY;
+ up->upstream_addr = PIMADDR_ANY;
}
}
}
@@ -826,15 +823,14 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
/* Find the upstream (*, G) whose upstream address is same as
* the deleted RP
*/
- if ((up->upstream_addr.s_addr ==
- rp_info->rp.rpf_addr.u.prefix4.s_addr) &&
+ pim_addr rpf_addr;
+
+ rpf_addr = pim_addr_from_prefix(&rp_info->rp.rpf_addr);
+ if (!pim_addr_cmp(up->upstream_addr, rpf_addr) &&
pim_addr_is_any(up->sg.src)) {
struct prefix grp;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
-
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
/* RP not found for the group grp */
@@ -918,9 +914,7 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr,
struct prefix grp;
struct rp_info *trp_info;
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&grp, up->sg.grp);
trp_info = pim_rp_find_match_group(pim, &grp);
if (trp_info == rp_info) {
@@ -1064,13 +1058,14 @@ void pim_i_am_rp_re_evaluate(struct pim_instance *pim)
}
}
+#if PIM_IPV == 4
/*
* I_am_RP(G) is true if the group-to-RP mapping indicates that
* this router is the RP for the group.
*
* Since we only have static RP, all groups are part of this RP
*/
-int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
+int pim_rp_i_am_rp(struct pim_instance *pim, pim_addr group)
{
struct prefix g;
struct rp_info *rp_info;
@@ -1084,7 +1079,6 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
if (rp_info)
return rp_info->i_am_rp;
-
return 0;
}
@@ -1093,7 +1087,7 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
*
* Return the RP that the Group belongs too.
*/
-struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
+struct pim_rpf *pim_rp_g(struct pim_instance *pim, pim_addr group)
{
struct prefix g;
struct rp_info *rp_info;
@@ -1135,8 +1129,8 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
* then set the upstream addr as INADDR_ANY and return failure.
*
*/
-int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
- struct in_addr source, struct in_addr group)
+int pim_rp_set_upstream_addr(struct pim_instance *pim, pim_addr *up,
+ pim_addr source, pim_addr group)
{
struct rp_info *rp_info;
struct prefix g;
@@ -1162,6 +1156,25 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
return 1;
}
+#else
+CPP_NOTICE("functions stubbed out for IPv6");
+
+int pim_rp_i_am_rp(struct pim_instance *pim, pim_addr group)
+{
+ return 0;
+}
+
+struct pim_rpf *pim_rp_g(struct pim_instance *pim, pim_addr group)
+{
+ return NULL;
+}
+
+int pim_rp_set_upstream_addr(struct pim_instance *pim, pim_addr *up,
+ pim_addr source, pim_addr group)
+{
+ return 0;
+}
+#endif
int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
const char *spaces)
@@ -1353,17 +1366,19 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
if (nbr->interface != ifp1)
continue;
+#if PIM_IPV == 4 || !defined(PIM_V6_TEMP_BREAK)
nh_node->gate.ipv4 = nbr->source_addr;
+#else
+ nh_node->gate.ipv6 = nbr->source_addr;
+#endif
if (PIM_DEBUG_PIM_NHT_RP) {
char str[PREFIX_STRLEN];
- char str1[INET_ADDRSTRLEN];
- pim_inet4_dump("<nht_nbr?>", nbr->source_addr,
- str1, sizeof(str1));
pim_addr_dump("<nht_addr?>", &nht_p, str,
sizeof(str));
zlog_debug(
- "%s: addr %s new nexthop addr %s interface %s",
- __func__, str, str1, ifp1->name);
+ "%s: addr %s new nexthop addr %pPAs interface %s",
+ __func__, str, &nbr->source_addr,
+ ifp1->name);
}
}
}
diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h
index 595025e5c9..c223402ddd 100644
--- a/pimd/pim_rp.h
+++ b/pimd/pim_rp.h
@@ -65,17 +65,17 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
void pim_rp_setup(struct pim_instance *pim);
-int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group);
+int pim_rp_i_am_rp(struct pim_instance *pim, pim_addr group);
void pim_rp_check_on_if_add(struct pim_interface *pim_ifp);
void pim_i_am_rp_re_evaluate(struct pim_instance *pim);
bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
struct in_addr dest_addr);
-int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
- struct in_addr source, struct in_addr group);
+int pim_rp_set_upstream_addr(struct pim_instance *pim, pim_addr *up,
+ pim_addr source, pim_addr group);
-struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group);
+struct pim_rpf *pim_rp_g(struct pim_instance *pim, pim_addr group);
#define I_am_RP(P, G) pim_rp_i_am_rp ((P), (G))
#define RP(P, G) pim_rp_g ((P), (G))
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 1e865a3956..2e8fc8e661 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -141,8 +141,8 @@ bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
i++;
} else if (neighbor_needed
&& !pim_if_connected_to_source(ifp, addr)) {
- nbr = pim_neighbor_find(
- ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(
+ ifp, &nexthop_tab[i].nexthop_addr);
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug("ifp name: %s, pim nbr: %p",
ifp->name, nbr);
@@ -234,7 +234,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags))
return PIM_RPF_OK;
- if (up->upstream_addr.s_addr == INADDR_ANY) {
+ if (pim_addr_is_any(up->upstream_addr)) {
zlog_debug("%s(%s): RP is not configured yet for %s",
__func__, caller, up->sg_str);
return PIM_RPF_OK;
@@ -248,16 +248,10 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
old->rpf_addr = saved.rpf_addr;
}
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+ pim_addr_to_prefix(&nht_p, up->upstream_addr);
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = up->upstream_addr; // RP or Src address
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&src, up->upstream_addr); // RP or Src address
+ pim_addr_to_prefix(&grp, up->sg.grp);
if ((pim_addr_is_any(up->sg.src) && I_am_RP(pim, up->sg.grp)) ||
PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
@@ -398,9 +392,11 @@ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up)
/* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */
- neigh = pim_if_find_neighbor(
- up->rpf.source_nexthop.interface,
- up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4);
+ pim_addr nhaddr;
+
+ nhaddr =
+ pim_addr_from_prefix(&up->rpf.source_nexthop.mrib_nexthop_addr);
+ neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, nhaddr);
if (neigh)
rpf_addr = neigh->source_addr;
else
diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c
index 6c5883aebf..45aac7756a 100644
--- a/pimd/pim_ssm.c
+++ b/pimd/pim_ssm.c
@@ -83,23 +83,20 @@ static int pim_is_grp_standard_ssm(struct prefix *group)
return prefix_match(&group_ssm, group);
}
-int pim_is_grp_ssm(struct pim_instance *pim, struct in_addr group_addr)
+int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr)
{
struct pim_ssm *ssm;
struct prefix group;
struct prefix_list *plist;
- memset(&group, 0, sizeof(group));
- group.family = AF_INET;
- group.u.prefix4 = group_addr;
- group.prefixlen = 32;
+ pim_addr_to_prefix(&group, group_addr);
ssm = pim->ssm_info;
if (!ssm->plist_name) {
return pim_is_grp_standard_ssm(&group);
}
- plist = prefix_list_lookup(AFI_IP, ssm->plist_name);
+ plist = prefix_list_lookup(PIM_AFI, ssm->plist_name);
if (!plist)
return 0;
diff --git a/pimd/pim_ssm.h b/pimd/pim_ssm.h
index 7235ade8dc..117713b866 100644
--- a/pimd/pim_ssm.h
+++ b/pimd/pim_ssm.h
@@ -34,7 +34,7 @@ struct pim_ssm {
void pim_ssm_prefix_list_update(struct pim_instance *pim,
struct prefix_list *plist);
-int pim_is_grp_ssm(struct pim_instance *pim, struct in_addr group_addr);
+int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr);
int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id,
const char *plist_name);
void *pim_ssm_init(void);
diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c
index a4f60e5198..86403dd54a 100644
--- a/pimd/pim_tlv.c
+++ b/pimd/pim_tlv.c
@@ -29,6 +29,12 @@
#include "pim_str.h"
#include "pim_msg.h"
+#if PIM_IPV == 4
+#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4
+#else
+#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV6
+#endif
+
uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend,
uint16_t option_type, uint16_t option_value)
{
@@ -117,7 +123,23 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
* The unicast address as represented by the given Address Family
* and Encoding Type.
*/
-int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p)
+int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr)
+{
+ uint8_t *start = buf;
+
+#if PIM_IPV == 4
+ *buf++ = PIM_MSG_ADDRESS_FAMILY_IPV4;
+#else
+ *buf++ = PIM_MSG_ADDRESS_FAMILY_IPV6;
+#endif
+ *buf++ = 0;
+ memcpy(buf, &addr, sizeof(addr));
+ buf += sizeof(addr);
+
+ return buf - start;
+}
+
+int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p)
{
switch (p->family) {
case AF_INET:
@@ -188,28 +210,22 @@ int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p)
* Contains the group address.
*/
int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
- struct in_addr group)
+ pim_addr group)
{
+ uint8_t *start = buf;
uint8_t flags = 0;
flags |= bidir << 8;
flags |= scope;
- switch (afi) {
- case AFI_IP:
- *buf = PIM_MSG_ADDRESS_FAMILY_IPV4;
- ++buf;
- *buf = 0;
- ++buf;
- *buf = flags;
- ++buf;
- *buf = 32;
- ++buf;
- memcpy(buf, &group, sizeof(struct in_addr));
- return group_ipv4_encoding_len;
- default:
- return 0;
- }
+ *buf++ = PIM_MSG_ADDRESS_FAMILY;
+ *buf++ = 0;
+ *buf++ = flags;
+ *buf++ = sizeof(group) / 8;
+ memcpy(buf, &group, sizeof(group));
+ buf += sizeof(group);
+
+ return buf - start;
}
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
@@ -248,7 +264,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
if (p->family != family)
continue;
- l_encode = pim_encode_addr_ucast(curr, p);
+ l_encode = pim_encode_addr_ucast_prefix(curr, p);
curr += l_encode;
option_len += l_encode;
}
@@ -274,15 +290,13 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
}
static int check_tlv_length(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
+ const char *ifname, pim_addr src_addr,
int correct_len, int option_len)
{
if (option_len != correct_len) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
zlog_warn(
- "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s",
- label, tlv_name, option_len, correct_len, src_str,
+ "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %pPAs on interface %s",
+ label, tlv_name, option_len, correct_len, &src_addr,
ifname);
return -1;
}
@@ -290,49 +304,44 @@ static int check_tlv_length(const char *label, const char *tlv_name,
return 0;
}
-static void check_tlv_redefinition_uint16(
- const char *label, const char *tlv_name, const char *ifname,
- struct in_addr src_addr, pim_hello_options options,
- pim_hello_options opt_mask, uint16_t new, uint16_t old)
+static void check_tlv_redefinition_uint16(const char *label,
+ const char *tlv_name,
+ const char *ifname, pim_addr src_addr,
+ pim_hello_options options,
+ pim_hello_options opt_mask,
+ uint16_t new, uint16_t old)
{
- if (PIM_OPTION_IS_SET(options, opt_mask)) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (PIM_OPTION_IS_SET(options, opt_mask))
zlog_warn(
- "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
- label, tlv_name, new, old, src_str, ifname);
- }
+ "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
+ label, tlv_name, new, old, &src_addr, ifname);
}
-static void check_tlv_redefinition_uint32(
- const char *label, const char *tlv_name, const char *ifname,
- struct in_addr src_addr, pim_hello_options options,
- pim_hello_options opt_mask, uint32_t new, uint32_t old)
+static void check_tlv_redefinition_uint32(const char *label,
+ const char *tlv_name,
+ const char *ifname, pim_addr src_addr,
+ pim_hello_options options,
+ pim_hello_options opt_mask,
+ uint32_t new, uint32_t old)
{
- if (PIM_OPTION_IS_SET(options, opt_mask)) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (PIM_OPTION_IS_SET(options, opt_mask))
zlog_warn(
- "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
- label, tlv_name, new, old, src_str, ifname);
- }
+ "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
+ label, tlv_name, new, old, &src_addr, ifname);
}
static void check_tlv_redefinition_uint32_hex(
const char *label, const char *tlv_name, const char *ifname,
- struct in_addr src_addr, pim_hello_options options,
+ pim_addr src_addr, pim_hello_options options,
pim_hello_options opt_mask, uint32_t new, uint32_t old)
{
- if (PIM_OPTION_IS_SET(options, opt_mask)) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ if (PIM_OPTION_IS_SET(options, opt_mask))
zlog_warn(
- "%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
- label, tlv_name, new, old, src_str, ifname);
- }
+ "%s: PIM hello TLV redefined %s=%08x old=%08x from %pPAs on interface %s",
+ label, tlv_name, new, old, &src_addr, ifname);
}
-int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint16_t *hello_option_holdtime, uint16_t option_len,
const uint8_t *tlv_curr)
@@ -356,7 +365,7 @@ int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
return 0;
}
-int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_lan_prune_delay(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint16_t *hello_option_propagation_delay,
uint16_t *hello_option_override_interval,
@@ -392,7 +401,7 @@ int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
return 0;
}
-int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_dr_priority(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_dr_priority,
uint16_t option_len, const uint8_t *tlv_curr)
@@ -416,7 +425,7 @@ int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
return 0;
}
-int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_generation_id(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_generation_id,
uint16_t option_len, const uint8_t *tlv_curr)
@@ -441,7 +450,8 @@ int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
return 0;
}
-int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size)
+int pim_parse_addr_ucast_prefix(struct prefix *p, const uint8_t *buf,
+ int buf_size)
{
const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
const uint8_t *addr;
@@ -510,6 +520,25 @@ int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size)
return addr - buf;
}
+int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size,
+ bool *wrong_af)
+{
+ struct prefix p;
+ int ret;
+
+ ret = pim_parse_addr_ucast_prefix(&p, buf, buf_size);
+ if (ret < 0)
+ return ret;
+
+ if (p.family != PIM_AF) {
+ *wrong_af = true;
+ return -5;
+ }
+
+ memcpy(out, &p.u.val, sizeof(*out));
+ return ret;
+}
+
int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size)
{
const int grp_encoding_min_len =
@@ -532,40 +561,32 @@ int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size)
family = *addr++;
type = *addr++;
- //++addr;
++addr; /* skip b_reserved_z fields */
mask_len = *addr++;
- switch (family) {
- case PIM_MSG_ADDRESS_FAMILY_IPV4:
- if (type) {
- zlog_warn(
- "%s: unknown group address encoding type=%d from",
- __func__, type);
- return -2;
- }
-
- if ((addr + sizeof(struct in_addr)) > pastend) {
- zlog_warn(
- "%s: IPv4 group address overflow: left=%td needed=%zu from",
- __func__, pastend - addr,
- sizeof(struct in_addr));
- return -3;
- }
-
- memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr));
-
- addr += sizeof(struct in_addr);
+ if (type) {
+ zlog_warn("%s: unknown group address encoding type=%d from",
+ __func__, type);
+ return -2;
+ }
- break;
- default: {
+ if (family != PIM_MSG_ADDRESS_FAMILY) {
zlog_warn(
"%s: unknown group address encoding family=%d mask_len=%d from",
__func__, family, mask_len);
return -4;
}
+
+ if ((addr + sizeof(sg->grp)) > pastend) {
+ zlog_warn(
+ "%s: group address overflow: left=%td needed=%zu from",
+ __func__, pastend - addr, sizeof(sg->grp));
+ return -3;
}
+ memcpy(&sg->grp, addr, sizeof(sg->grp));
+ addr += sizeof(sg->grp);
+
return addr - buf;
}
@@ -654,7 +675,7 @@ int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf,
} \
}
-int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_addr_list(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
struct list **hello_option_addr_list,
uint16_t option_len, const uint8_t *tlv_curr)
@@ -670,20 +691,18 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
addr = tlv_curr;
pastend = tlv_curr + option_len;
while (addr < pastend) {
- struct prefix tmp;
+ struct prefix tmp, src_pfx;
int addr_offset;
/*
Parse ucast addr
*/
- addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr);
+ addr_offset =
+ pim_parse_addr_ucast_prefix(&tmp, addr, pastend - addr);
if (addr_offset < 1) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
zlog_warn(
- "%s: pim_parse_addr_ucast() failure: from %s on %s",
- __func__, src_str, ifname);
+ "%s: pim_parse_addr_ucast() failure: from %pPAs on %s",
+ __func__, &src_addr, ifname);
FREE_ADDR_LIST(*hello_option_addr_list);
return -1;
}
@@ -696,35 +715,28 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
switch (tmp.family) {
case AF_INET: {
char addr_str[INET_ADDRSTRLEN];
- char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>", tmp.u.prefix4,
addr_str, sizeof(addr_str));
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
zlog_debug(
- "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s",
+ "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %pPAs on %s",
__func__,
*hello_option_addr_list
? ((int)listcount(
- *hello_option_addr_list))
+ *hello_option_addr_list))
: -1,
- addr_str, src_str, ifname);
+ addr_str, &src_addr, ifname);
} break;
case AF_INET6:
break;
- default: {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
+ default:
zlog_debug(
- "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
+ "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %pPAs on %s",
__func__,
*hello_option_addr_list
? ((int)listcount(
- *hello_option_addr_list))
+ *hello_option_addr_list))
: -1,
- src_str, ifname);
- }
+ &src_addr, ifname);
}
}
@@ -732,16 +744,12 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
Exclude neighbor's primary address if incorrectly included in
the secondary address list
*/
- if (tmp.family == AF_INET) {
- if (tmp.u.prefix4.s_addr == src_addr.s_addr) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str,
- sizeof(src_str));
- zlog_warn(
- "%s: ignoring primary address in secondary list from %s on %s",
- __func__, src_str, ifname);
- continue;
- }
+ pim_addr_to_prefix(&src_pfx, src_addr);
+ if (!prefix_cmp(&tmp, &src_pfx)) {
+ zlog_warn(
+ "%s: ignoring primary address in secondary list from %pPAs on %s",
+ __func__, &src_addr, ifname);
+ continue;
}
/*
diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h
index 1aa60d5dbb..64b3a0b6ba 100644
--- a/pimd/pim_tlv.h
+++ b/pimd/pim_tlv.h
@@ -84,33 +84,37 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
struct list *ifconnected, int family);
-int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint16_t *hello_option_holdtime, uint16_t option_len,
const uint8_t *tlv_curr);
-int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_lan_prune_delay(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint16_t *hello_option_propagation_delay,
uint16_t *hello_option_override_interval,
uint16_t option_len, const uint8_t *tlv_curr);
-int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_dr_priority(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_dr_priority,
uint16_t option_len, const uint8_t *tlv_curr);
-int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_generation_id(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_generation_id,
uint16_t option_len, const uint8_t *tlv_curr);
-int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
+int pim_tlv_parse_addr_list(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
struct list **hello_option_addr_list,
uint16_t option_len, const uint8_t *tlv_curr);
-int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p);
+int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr);
+int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p);
int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
- struct in_addr group);
+ pim_addr group);
-int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size);
+int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size,
+ bool *wrong_af);
+int pim_parse_addr_ucast_prefix(struct prefix *out, const uint8_t *buf,
+ int buf_size);
int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size);
int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf,
int buf_size);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 800ec9c45c..a410a1c2ce 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -259,11 +259,9 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
* to INADDR_ANY. This is done in order to avoid de-registering for
* 255.255.255.255 which is maintained for some reason..
*/
- if (up->upstream_addr.s_addr != INADDR_ANY) {
+ if (!pim_addr_is_any(up->upstream_addr)) {
/* Deregister addr with Zebra NHT */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = up->upstream_addr;
+ pim_addr_to_prefix(&nht_p, up->upstream_addr);
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s: Deregister upstream %s addr %pFX with Zebra NHT",
@@ -343,8 +341,8 @@ static void join_timer_stop(struct pim_upstream *up)
THREAD_OFF(up->t_join_timer);
if (up->rpf.source_nexthop.interface)
- nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(up->rpf.source_nexthop.interface,
+ &up->rpf.rpf_addr);
if (nbr)
pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
@@ -357,8 +355,8 @@ void join_timer_start(struct pim_upstream *up)
struct pim_neighbor *nbr = NULL;
if (up->rpf.source_nexthop.interface) {
- nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(up->rpf.source_nexthop.interface,
+ &up->rpf.rpf_addr);
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug(
@@ -449,8 +447,8 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
pim_time_timer_remain_msec(up->t_join_timer);
else {
/* Remove it from jp agg from the nbr for suppression */
- nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(up->rpf.source_nexthop.interface,
+ &up->rpf.rpf_addr);
if (nbr) {
join_timer_remain_msec =
pim_time_timer_remain_msec(nbr->jp_timer);
@@ -504,8 +502,8 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
/* upstream join tracked with neighbor jp timer */
struct pim_neighbor *nbr;
- nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
- up->rpf.rpf_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(up->rpf.source_nexthop.interface,
+ &up->rpf.rpf_addr);
if (nbr)
join_timer_remain_msec =
pim_time_timer_remain_msec(nbr->jp_timer);
@@ -713,7 +711,7 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
{
enum pim_upstream_state old_state = up->join_state;
- if (up->upstream_addr.s_addr == INADDR_ANY) {
+ if (pim_addr_is_any(up->upstream_addr)) {
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug("%s: RPF not configured for %s", __func__,
up->sg_str);
@@ -937,7 +935,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags))
pim_upstream_keep_alive_timer_start(
up, pim->keep_alive_time);
- } else if (up->upstream_addr.s_addr != INADDR_ANY) {
+ } else if (!pim_addr_is_any(up->upstream_addr)) {
pim_upstream_update_use_rpt(up,
false /*update_mroute*/);
rpf_result = pim_rpf_update(pim, up, NULL, __func__);
@@ -1274,15 +1272,13 @@ void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
*/
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
if (PIM_DEBUG_PIM_TRACE) {
- char neigh_str[INET_ADDRSTRLEN];
char rpf_addr_str[PREFIX_STRLEN];
- pim_inet4_dump("<neigh?>", neigh_addr, neigh_str,
- sizeof(neigh_str));
pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str,
sizeof(rpf_addr_str));
zlog_debug(
- "%s: matching neigh=%s against upstream (S,G)=%s[%s] joined=%d rpf_addr=%s",
- __func__, neigh_str, up->sg_str, pim->vrf->name,
+ "%s: matching neigh=%pI4 against upstream (S,G)=%s[%s] joined=%d rpf_addr=%s",
+ __func__, &neigh_addr, up->sg_str,
+ pim->vrf->name,
up->join_state == PIM_UPSTREAM_JOINED,
rpf_addr_str);
}
@@ -1914,7 +1910,7 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
* Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
*/
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
- if (up->upstream_addr.s_addr == INADDR_ANY) {
+ if (pim_addr_is_any(up->upstream_addr)) {
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s: RP not configured for Upstream %s",
@@ -2153,10 +2149,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
struct prefix g;
enum prefix_list_type apply_new;
- np = prefix_list_lookup(AFI_IP, nlist);
-
- g.family = AF_INET;
- g.prefixlen = IPV4_MAX_BITLEN;
+ np = prefix_list_lookup(PIM_AFI, nlist);
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
if (!pim_addr_is_any(up->sg.src))
@@ -2170,7 +2163,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
PIM_OIF_FLAG_PROTO_IGMP, __func__);
continue;
}
- g.u.prefix4 = up->sg.grp;
+ pim_addr_to_prefix(&g, up->sg.grp);
apply_new = prefix_list_apply(np, &g);
if (apply_new == PREFIX_DENY)
pim_channel_add_oif(up->channel_oil, pim->regiface,
diff --git a/pimd/pim_util.c b/pimd/pim_util.c
index decc491ede..8232d7205b 100644
--- a/pimd/pim_util.c
+++ b/pimd/pim_util.c
@@ -139,7 +139,7 @@ int pim_is_group_224_4(struct in_addr group_addr)
return prefix_match(&group_all, &group);
}
-bool pim_is_group_filtered(struct pim_interface *pim_ifp, struct in_addr *grp)
+bool pim_is_group_filtered(struct pim_interface *pim_ifp, pim_addr *grp)
{
struct prefix grp_pfx;
struct prefix_list *pl;
@@ -147,10 +147,8 @@ bool pim_is_group_filtered(struct pim_interface *pim_ifp, struct in_addr *grp)
if (!pim_ifp->boundary_oil_plist)
return false;
- grp_pfx.family = AF_INET;
- grp_pfx.prefixlen = IPV4_MAX_BITLEN;
- grp_pfx.u.prefix4 = *grp;
+ pim_addr_to_prefix(&grp_pfx, *grp);
- pl = prefix_list_lookup(AFI_IP, pim_ifp->boundary_oil_plist);
+ pl = prefix_list_lookup(PIM_AFI, pim_ifp->boundary_oil_plist);
return pl ? prefix_list_apply(pl, &grp_pfx) == PREFIX_DENY : false;
}
diff --git a/pimd/pim_util.h b/pimd/pim_util.h
index c66dd7b660..b9c227996e 100644
--- a/pimd/pim_util.h
+++ b/pimd/pim_util.h
@@ -35,5 +35,5 @@ void pim_pkt_dump(const char *label, const uint8_t *buf, int size);
int pim_is_group_224_0_0_0_24(struct in_addr group_addr);
int pim_is_group_224_4(struct in_addr group_addr);
-bool pim_is_group_filtered(struct pim_interface *pim_ifp, struct in_addr *grp);
+bool pim_is_group_filtered(struct pim_interface *pim_ifp, pim_addr *grp);
#endif /* PIM_UTIL_H */
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index c543c63eeb..8130aac872 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -341,13 +341,9 @@ int pim_interface_config_write(struct vty *vty)
/* update source */
if (!pim_addr_is_any(pim_ifp->update_source)) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>",
- pim_ifp->update_source,
- src_str,
- sizeof(src_str));
- vty_out(vty, " ip pim use-source %s\n",
- src_str);
+ vty_out(vty,
+ " ip pim use-source %pPA\n",
+ &pim_ifp->update_source);
++writes;
}
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index c1e7be5870..39a1a32a5b 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -354,9 +354,7 @@ static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
* iif
*/
if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) {
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = up->upstream_addr;
+ pim_addr_to_prefix(&nht_p, up->upstream_addr);
pim_delete_tracked_nexthop(vxlan_sg->pim, &nht_p, up,
NULL);
}
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 2efafd4b9b..11b13db318 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -141,12 +141,14 @@ static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
#endif
}
- if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
- /* trying to add primary address */
-
- struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
- if (p->family != AF_INET
- || primary_addr.s_addr != p->u.prefix4.s_addr) {
+ if (p->family != PIM_AF)
+ SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
+ else if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
+ /* trying to add primary address? */
+ pim_addr primary_addr = pim_find_primary_addr(c->ifp);
+ pim_addr addr = pim_addr_from_prefix(p);
+
+ if (pim_addr_cmp(primary_addr, addr)) {
if (PIM_DEBUG_ZEBRA)
zlog_warn(
"%s: %s : forcing secondary flag on %pFX",
@@ -254,8 +256,8 @@ void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
if (old->source_nexthop.interface) {
struct pim_neighbor *nbr;
- nbr = pim_neighbor_find(old->source_nexthop.interface,
- old->rpf_addr.u.prefix4);
+ nbr = pim_neighbor_find_prefix(old->source_nexthop.interface,
+ &old->rpf_addr);
if (nbr)
pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
@@ -337,8 +339,8 @@ static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS)
s = zclient->ibuf;
prefixlen = stream_getl(s);
- stream_get(&sg.src.s_addr, s, prefixlen);
- stream_get(&sg.grp.s_addr, s, prefixlen);
+ stream_get(&sg.src, s, prefixlen);
+ stream_get(&sg.grp, s, prefixlen);
if (PIM_DEBUG_ZEBRA)
zlog_debug("%u:recv SG %s %pSG", vrf_id,
@@ -606,7 +608,7 @@ void igmp_source_forward_start(struct pim_instance *pim,
}
if (!source->source_channel_oil) {
- struct in_addr vif_source;
+ pim_addr vif_source;
struct prefix src, grp;
struct pim_nexthop nexthop;
struct pim_upstream *up = NULL;
@@ -619,12 +621,8 @@ void igmp_source_forward_start(struct pim_instance *pim,
}
else {
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = vif_source; // RP or Src address
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = sg.grp;
+ pim_addr_to_prefix(&src, vif_source); // RP or Src addr
+ pim_addr_to_prefix(&grp, sg.grp);
up = pim_upstream_find(pim, &sg);
if (up) {
@@ -642,15 +640,11 @@ void igmp_source_forward_start(struct pim_instance *pim,
pim_ecmp_fib_lookup_if_vif_index(
pim, &src, &grp);
- if (PIM_DEBUG_ZEBRA) {
- char buf2[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<source?>", vif_source, buf2,
- sizeof(buf2));
- zlog_debug("%s: NHT %pSG vif_source %s vif_index:%d ",
- __func__, &sg, buf2,
- input_iface_vif_index);
- }
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug(
+ "%s: NHT %pSG vif_source %pPAs vif_index:%d ",
+ __func__, &sg, &vif_source,
+ input_iface_vif_index);
if (input_iface_vif_index < 1) {
if (PIM_DEBUG_IGMP_TRACE) {
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 5997cc25a4..b169335a3a 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -300,9 +300,9 @@ static int zclient_read_nexthop(struct pim_instance *pim,
if (nbr) {
nexthop_tab[num_ifindex].nexthop_addr.family =
AF_INET;
- nexthop_tab[num_ifindex]
- .nexthop_addr.u.prefix4 =
- nbr->source_addr;
+ pim_addr_to_prefix(
+ &nexthop_tab[num_ifindex].nexthop_addr,
+ nbr->source_addr);
}
++num_ifindex;
break;
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 992bb931bd..9621f9794d 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -49,15 +49,22 @@
CPP_NOTICE("Work needs to be done to make this work properly via the pim mroute socket\n");
#endif /* MAXVIFS > 256 */
+#if PIM_IPV == 4
const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS;
const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS;
const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS;
const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS;
+#else
+const char *const PIM_ALL_SYSTEMS = "ff02::1";
+const char *const PIM_ALL_ROUTERS = "ff02::2";
+const char *const PIM_ALL_PIM_ROUTERS = "ff02::d";
+const char *const PIM_ALL_IGMP_ROUTERS = "ff02::16";
+#endif
DEFINE_MTYPE_STATIC(PIMD, ROUTER, "PIM Router information");
struct pim_router *router = NULL;
-struct in_addr qpim_all_pim_routers_addr;
+pim_addr qpim_all_pim_routers_addr;
void pim_prefix_list_update(struct prefix_list *plist)
{
@@ -103,7 +110,7 @@ void pim_router_init(void)
PIM_ASSERT_METRIC_PREFERENCE_MAX;
router->infinite_assert_metric.route_metric =
PIM_ASSERT_ROUTE_METRIC_MAX;
- router->infinite_assert_metric.ip_address.s_addr = INADDR_ANY;
+ router->infinite_assert_metric.ip_address = PIMADDR_ANY;
router->rpf_cache_refresh_delay_msec = 50;
router->register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
@@ -120,7 +127,8 @@ void pim_router_terminate(void)
void pim_init(void)
{
- if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) {
+ if (!inet_pton(PIM_AF, PIM_ALL_PIM_ROUTERS,
+ &qpim_all_pim_routers_addr)) {
flog_err(
EC_LIB_SOCKET,
"%s %s: could not solve %s to group address: errno=%d: %s",
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 7732dc5b74..d4eac58a29 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -134,7 +134,7 @@ extern const char *const PIM_ALL_PIM_ROUTERS;
extern const char *const PIM_ALL_IGMP_ROUTERS;
extern struct zebra_privs_t pimd_privs;
-extern struct in_addr qpim_all_pim_routers_addr;
+extern pim_addr qpim_all_pim_routers_addr;
extern uint8_t qpim_ecmp_enable;
extern uint8_t qpim_ecmp_rebalance_enable;
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index c2d39752ab..7288dc0869 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -1062,8 +1062,7 @@ static void parse_test(struct test_segment *t)
printf("\n");
- if (asp)
- aspath_unintern(&asp);
+ aspath_unintern(&asp);
}
/* prepend testing */
@@ -1117,8 +1116,7 @@ static void empty_prepend_test(struct test_segment *t)
printf(FAILED "!\n");
printf("\n");
- if (asp1)
- aspath_unintern(&asp1);
+ aspath_unintern(&asp1);
aspath_free(asp2);
}
@@ -1277,10 +1275,8 @@ static int handle_attr_test(struct aspath_tests *t)
}
out:
- if (attr.aspath)
- aspath_unintern(&attr.aspath);
- if (asp)
- aspath_unintern(&asp);
+ aspath_unintern(&attr.aspath);
+ aspath_unintern(&asp);
return failed - initfail;
}
diff --git a/tests/topotests/bgp_route_map/test_route_map_topo1.py b/tests/topotests/bgp_route_map/test_route_map_topo1.py
index 3c2d7f28a2..6556c050bb 100644
--- a/tests/topotests/bgp_route_map/test_route_map_topo1.py
+++ b/tests/topotests/bgp_route_map/test_route_map_topo1.py
@@ -444,9 +444,10 @@ def test_route_map_inbound_outbound_same_neighbor_p0(request):
result = verify_rib(
tgen, adt, dut, input_dict_2, protocol=protocol, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- "routes are not present in rib \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nroutes are not present in rib \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected behaviour: {}".format(result))
@@ -466,9 +467,10 @@ def test_route_map_inbound_outbound_same_neighbor_p0(request):
result = verify_rib(
tgen, adt, dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "routes are not present in rib \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nroutes are not present in rib \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected behaviour: {}".format(result))
@@ -664,9 +666,10 @@ def test_route_map_with_action_values_combination_of_prefix_action_p0(
result = verify_rib(
tgen, adt, dut, input_dict_2, protocol=protocol, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "Routes are still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nRoutes are still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected behaviour: {}".format(result))
else:
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 551483d718..34afa0d2c1 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -3677,7 +3677,7 @@ def verify_f_bit(tgen, topo, addr_type, input_dict, dut, peer, expected=True):
@retry(retry_timeout=10)
def verify_graceful_restart_timers(tgen, topo, addr_type, input_dict, dut, peer):
"""
- This API is to verify graceful restart timers, configured and recieved
+ This API is to verify graceful restart timers, configured and received
Parameters
----------
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 92d29ad1ab..8d2bf12af2 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -1933,7 +1933,7 @@ def verify_ospf6_interface(tgen, topo=None, dut=None, lan=False, input_dict=None
True or False (Error Message)
"""
- logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ logger.debug("Entering lib API: verify_ospf6_interface")
result = False
if topo is None:
@@ -2311,6 +2311,7 @@ def config_ospf6_interface(
-------
True or False
"""
+
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
result = False
if topo is None:
@@ -2337,6 +2338,7 @@ def config_ospf6_interface(
ospf_data = input_dict[router]["links"][lnk]["ospf6"]
data_ospf_area = ospf_data.setdefault("area", None)
data_ospf_auth = ospf_data.setdefault("hash-algo", None)
+ data_ospf_keychain = ospf_data.setdefault("keychain", None)
data_ospf_dr_priority = ospf_data.setdefault("priority", None)
data_ospf_cost = ospf_data.setdefault("cost", None)
data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None)
@@ -2369,9 +2371,18 @@ def config_ospf6_interface(
ospf_data["hash-algo"],
ospf_data["key"],
)
- if "del_action" in ospf_data:
- cmd = "no {}".format(cmd)
- config_data.append(cmd)
+ config_data.append(cmd)
+
+ # interface ospf auth with keychain
+ if data_ospf_keychain:
+ cmd = "ipv6 ospf6 authentication"
+
+ if "del_action" in ospf_data:
+ cmd = "no {}".format(cmd)
+
+ if "keychain" in ospf_data:
+ cmd = "{} keychain {}".format(cmd, ospf_data["keychain"])
+ config_data.append(cmd)
# interface ospf dr priority
if data_ospf_dr_priority:
diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
index a8418d400d..4ab160b52e 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -501,7 +501,7 @@ def test_BSR_higher_prefer_ip_p0(request):
step("sleeping for 3 sec to leran new packet")
do_countdown(3)
- step("verify BSR1 is become prefered RP")
+ step("verify BSR1 has become preferred RP")
dut = "l1"
step("Verify if b1 chosen as BSR in f1")
@@ -521,7 +521,7 @@ def test_BSR_higher_prefer_ip_p0(request):
do_countdown(3)
f1_b2_eth1 = topo["routers"]["f1"]["links"]["b2"]["interface"]
shutdown_bringup_interface(tgen, "f1", "f1-b2-eth1", True)
- step("verify BSR2 is become prefered RP")
+ step("verify BSR2 has become preferred RP")
dut = "l1"
step("Send BSR packet from b1 and b2 to FHR")
diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_authentication.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_authentication.json
new file mode 100644
index 0000000000..08ff253b75
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_authentication.json
@@ -0,0 +1,169 @@
+{
+ "address_types": [
+ "ipv6"
+ ],
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r0": {
+ "links": {
+ "r1": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r2": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r3": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "100.1.1.0",
+ "neighbors": {
+ "r1": {},
+ "r2": {},
+ "r3": {}
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "r1": {
+ "links": {
+ "r0": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r2": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r3": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "100.1.1.1",
+ "neighbors": {
+ "r0": {},
+ "r2": {},
+ "r3": {}
+ }
+ }
+ },
+ "r2": {
+ "links": {
+ "r0": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r1": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r3": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "100.1.1.2",
+ "neighbors": {
+ "r1": {},
+ "r0": {},
+ "r3": {}
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "r0": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r1": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ },
+ "r2": {
+ "ipv6": "auto",
+ "ospf6": {
+ "area": "0.0.0.0",
+ "hello_interval": 1,
+ "dead_interval": 4
+ }
+ }
+ },
+ "ospf6": {
+ "router_id": "100.1.1.3",
+ "neighbors": {
+ "r0": {},
+ "r1": {},
+ "r2": {}
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
new file mode 100644
index 0000000000..baa0071f9c
--- /dev/null
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
@@ -0,0 +1,1446 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2021 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
+# ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+
+"""OSPF Basic Functionality Automation."""
+import os
+import sys
+import time
+import pytest
+from time import sleep
+from copy import deepcopy
+import json
+from lib.topotest import frr_unicode
+
+pytestmark = pytest.mark.ospf6d
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+# Import topoJson from lib, to create topology and initial configuration
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ step,
+ shutdown_bringup_interface,
+ topo_daemons,
+)
+from lib.topolog import logger
+from lib.topojson import build_topo_from_json, build_config_from_json
+from lib.ospf import verify_ospf6_neighbor, config_ospf6_interface, clear_ospf
+from ipaddress import IPv4Address
+
+# Global variables
+topo = None
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/ospfv3_authentication.json".format(CWD)
+try:
+ with open(jsonFile, "r") as topoJson:
+ topo = json.load(topoJson)
+except IOError:
+ assert False, "Could not read file {}".format(jsonFile)
+"""
+TOPOOLOGY =
+ Please view in a fixed-width font such as Courier.
+ +---+ A1 +---+
+ +R1 +------------+R2 |
+ +-+-+- +--++
+ | -- -- |
+ | -- A0 -- |
+ A0| ---- |
+ | ---- | A2
+ | -- -- |
+ | -- -- |
+ +-+-+- +-+-+
+ +R0 +-------------+R3 |
+ +---+ A3 +---+
+
+TESTCASES =
+1. OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 manual key configuration.
+2. OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 manual key configuration.
+3. OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 keychain configuration.
+4. OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 keychain configuration.
+
+ """
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+ * `mod`: module name
+ """
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/ospfv3_single_area.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, topo)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen, daemons)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo)
+ assert ospf6_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf6_covergence
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """
+ Teardown the pytest environment.
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+# ##################################
+# Test cases start here.
+# ##################################
+
+def test_ospf6_auth_trailer_tc1_md5(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 manual key configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Disable authentication on R2 "
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ "del_action": True
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R1 ,nbr is deleted for R2 after dead interval expiry")
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Again On R2 enable ospf6 on interface with message-digest auth")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using"
+ " show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Shut no shut interface on R1")
+ dut = "r1"
+ intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ dut = "r2"
+ step(
+ "Verify that the neighbour is not FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ dut = "r1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_ospf6_auth_trailer_tc2_sha256(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 manual key configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Disable authentication on R2 "
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ "del_action": True
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R1 ,nbr is deleted for R2 after dead interval expiry")
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Again On R2 enable ospf6 on interface with message-digest auth")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using"
+ " show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Shut no shut interface on R1")
+ dut = "r1"
+ intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ dut = "r2"
+ step(
+ "Verify that the neighbour is not FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ dut = "r1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc3_keychain_md5(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 keychain configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ router1.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm md5"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm md5"""
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Disable authentication on R2 "
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ "del_action": True
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R1 ,nbr is deleted for R2 after dead interval expiry")
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Again On R2 enable ospf6 on interface with message-digest auth")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using"
+ " show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Shut no shut interface on R1")
+ dut = "r1"
+ intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ dut = "r2"
+ step(
+ "Verify that the neighbour is not FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ dut = "r1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 keychain configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ router1.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm hmac-sha-256"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm hmac-sha-256"""
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Disable authentication on R2 "
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ "del_action": True
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify on R1 ,nbr is deleted for R2 after dead interval expiry")
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Again On R2 enable ospf6 on interface with message-digest auth")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using"
+ " show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Shut no shut interface on R1")
+ dut = "r1"
+ intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ dut = "r2"
+ step(
+ "Verify that the neighbour is not FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ dut = "r1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 manual key configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer wrong key"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6-missmatch",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is not FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ step("Verify that the neighbour is FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer correct key"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "md5",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 manual key configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 with on R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer wrong key"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6-missmatch",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 with on R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer wrong key"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using MD5 keychain configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ router1.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm md5"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm md5"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth-missmatch
+ key 10
+ key-string ospf6-missmatch
+ cryptographic-algorithm md5"""
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer with wrong keychain"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth-missmatch",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer with correct keychain"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
+ """
+ OSPFv3 Authentication Trailer - Verify ospfv3 authentication trailer
+ using HMAC-SHA-256 keychain configuration.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ router1.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm hmac-sha-256"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth
+ key 10
+ key-string ospf6
+ cryptographic-algorithm hmac-sha-256"""
+ )
+
+ router2.vtysh_cmd(
+ """configure terminal
+ key chain auth-missmatch
+ key 10
+ key-string ospf6-missmatch
+ cryptographic-algorithm hmac-sha-256"""
+ )
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer wrong keychain"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth-missmatch",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer correct keychain"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc9_keychain_not_configured(request):
+ """
+ OSPFv3 Neighborship without Authentication Trailer -
+ Verify ospfv3 neighborship when no authentication trailer is configured.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 auth on R1 interface "
+ "connected to R2 with auth trailer"
+ )
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ r1_ospf6_auth = {
+ "r1": {
+ "links": {
+ "r2": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r1"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step(
+ "Configure ospf6 between R1 and R2, enable ospf6 on R2 interface "
+ "connected to R1 with auth trailer non existing keychain"
+ )
+
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "keychain": "auth",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that the neighbour is not FULL between R1 and R2.")
+ # wait for dead time expiry.
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=3
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+def test_ospf6_auth_trailer_tc10_no_auth_trailer(request):
+ """
+ OSPFv3 Neighborship without Authentication Trailer -
+ Verify ospfv3 neighborship when no authentication trailer is configured.
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ global topo
+ step("Bring up the base config.")
+ reset_config_on_routers(tgen)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+
+ step(
+ "Verify that the neighbour is FULL between R1 and R2 "
+ "using show ipv6 ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error:" " {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ write_test_footer(tc_name)
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index 334bd7affa..c2b4e779de 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -91,7 +91,7 @@ sub scan_file {
# $protocol is VTYSH_PROTO format for redirection of user input
if ($file =~ /lib\/keychain\.c$/) {
- $protocol = "VTYSH_RIPD|VTYSH_EIGRPD";
+ $protocol = "VTYSH_RIPD|VTYSH_EIGRPD|VTYSH_OSPF6D";
}
elsif ($file =~ /lib\/routemap\.c$/ || $file =~ /lib\/routemap_cli\.c$/) {
$protocol = "VTYSH_RMAP";
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 8e95aaa47c..336fe8b30e 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -818,7 +818,7 @@ int vtysh_mark_file(const char *filename)
return 0;
}
-/* Configration make from file. */
+/* Configuration make from file. */
int vtysh_config_from_file(struct vty *vty, FILE *fp)
{
int ret;
@@ -1586,7 +1586,7 @@ DEFUNSH(VTYSH_REALLYALL, vtysh_end_all, vtysh_end_all_cmd, "end",
DEFUNSH(VTYSH_ZEBRA, srv6, srv6_cmd,
"srv6",
- "Segment-Routing SRv6 configration\n")
+ "Segment-Routing SRv6 configuration\n")
{
vty->node = SRV6_NODE;
return CMD_SUCCESS;
@@ -1594,7 +1594,7 @@ DEFUNSH(VTYSH_ZEBRA, srv6, srv6_cmd,
DEFUNSH(VTYSH_ZEBRA, srv6_locators, srv6_locators_cmd,
"locators",
- "Segment-Routing SRv6 locators configration\n")
+ "Segment-Routing SRv6 locators configuration\n")
{
vty->node = SRV6_LOCS_NODE;
return CMD_SUCCESS;
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index e56d482da2..66af248354 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -57,7 +57,7 @@ DECLARE_MGROUP(MVTYSH);
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_FABRICD
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD|VTYSH_VRRPD
#define VTYSH_VRF VTYSH_INTERFACE|VTYSH_STATICD
-#define VTYSH_KEYS VTYSH_RIPD|VTYSH_EIGRPD
+#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D
/* Daemons who can process nexthop-group configs */
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
#define VTYSH_SR VTYSH_ZEBRA|VTYSH_PATHD
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index 76956574cc..a4f27b61cb 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -587,7 +587,7 @@ int main(int argc, char **argv, char **env)
* Setup history file for use by both -c and regular input
* If we can't find the home directory, then don't store
* the history information.
- * VTYSH_HISTFILE is prefered over command line
+ * VTYSH_HISTFILE is preferred over command line
* argument (-H/--histfile).
*/
if (getenv("VTYSH_HISTFILE")) {
diff --git a/yang/frr-pathd.yang b/yang/frr-pathd.yang
index 30f9875a6d..5beda769c1 100644
--- a/yang/frr-pathd.yang
+++ b/yang/frr-pathd.yang
@@ -414,7 +414,7 @@ module frr-pathd {
container objective-function {
presence "If the candidate has an objective function constraint";
description
- "Define objective function constraint as a list of prefered functions";
+ "Define objective function constraint as a list of preferred functions";
leaf required {
type boolean;
default "true";
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index 0e0ccccb6a..825497fff3 100644
--- a/zebra/debug_nl.c
+++ b/zebra/debug_nl.c
@@ -24,6 +24,7 @@
#include <linux/nexthop.h>
#include <linux/rtnetlink.h>
#include <net/if_arp.h>
+#include <linux/fib_rules.h>
#include <stdio.h>
#include <stdint.h>
@@ -576,6 +577,86 @@ const char *nhm_rta2str(int type)
}
}
+const char *frh_rta2str(int type)
+{
+ switch (type) {
+ case FRA_DST:
+ return "DST";
+ case FRA_SRC:
+ return "SRC";
+ case FRA_IIFNAME:
+ return "IIFNAME";
+ case FRA_GOTO:
+ return "GOTO";
+ case FRA_UNUSED2:
+ return "UNUSED2";
+ case FRA_PRIORITY:
+ return "PRIORITY";
+ case FRA_UNUSED3:
+ return "UNUSED3";
+ case FRA_UNUSED4:
+ return "UNUSED4";
+ case FRA_UNUSED5:
+ return "UNUSED5";
+ case FRA_FWMARK:
+ return "FWMARK";
+ case FRA_FLOW:
+ return "FLOW";
+ case FRA_TUN_ID:
+ return "TUN_ID";
+ case FRA_SUPPRESS_IFGROUP:
+ return "SUPPRESS_IFGROUP";
+ case FRA_SUPPRESS_PREFIXLEN:
+ return "SUPPRESS_PREFIXLEN";
+ case FRA_TABLE:
+ return "TABLE";
+ case FRA_FWMASK:
+ return "FWMASK";
+ case FRA_OIFNAME:
+ return "OIFNAME";
+ case FRA_PAD:
+ return "PAD";
+ case FRA_L3MDEV:
+ return "L3MDEV";
+ case FRA_UID_RANGE:
+ return "UID_RANGE";
+ case FRA_PROTOCOL:
+ return "PROTOCOL";
+ case FRA_IP_PROTO:
+ return "IP_PROTO";
+ case FRA_SPORT_RANGE:
+ return "SPORT_RANGE";
+ case FRA_DPORT_RANGE:
+ return "DPORT_RANGE";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+const char *frh_action2str(uint8_t action)
+{
+ switch (action) {
+ case FR_ACT_TO_TBL:
+ return "TO_TBL";
+ case FR_ACT_GOTO:
+ return "GOTO";
+ case FR_ACT_NOP:
+ return "NOP";
+ case FR_ACT_RES3:
+ return "RES3";
+ case FR_ACT_RES4:
+ return "RES4";
+ case FR_ACT_BLACKHOLE:
+ return "BLACKHOLE";
+ case FR_ACT_UNREACHABLE:
+ return "UNREACHABLE";
+ case FR_ACT_PROHIBIT:
+ return "PROHIBIT";
+ default:
+ return "UNKNOWN";
+ }
+}
+
static inline void flag_write(int flags, int flag, const char *flagstr,
char *buf, size_t buflen)
{
@@ -1110,6 +1191,111 @@ next_rta:
goto next_rta;
}
+static void nlrule_dump(struct fib_rule_hdr *frh, size_t msglen)
+{
+ struct rtattr *rta;
+ size_t plen;
+ uint8_t u8v;
+ uint32_t u32v;
+ int32_t s32v;
+ uint64_t u64v;
+ char dbuf[128];
+ struct fib_rule_uid_range *u_range;
+ struct fib_rule_port_range *p_range;
+
+ /* Get the first attribute and go from there. */
+ rta = RTM_RTA(frh);
+next_rta:
+ /* Check the header for valid length and for outbound access. */
+ if (RTA_OK(rta, msglen) == 0)
+ return;
+
+ plen = RTA_PAYLOAD(rta);
+ zlog_debug(" rta [len=%d (payload=%zu) type=(%d) %s]", rta->rta_len,
+ plen, rta->rta_type, frh_rta2str(rta->rta_type));
+ switch (rta->rta_type) {
+ case FRA_DST:
+ case FRA_SRC:
+ switch (plen) {
+ case sizeof(struct in_addr):
+ zlog_debug(" %pI4",
+ (struct in_addr *)RTA_DATA(rta));
+ break;
+ case sizeof(struct in6_addr):
+ zlog_debug(" %pI6",
+ (struct in6_addr *)RTA_DATA(rta));
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case FRA_IIFNAME:
+ case FRA_OIFNAME:
+ snprintf(dbuf, sizeof(dbuf), "%s", (char *)RTA_DATA(rta));
+ zlog_debug(" %s", dbuf);
+ break;
+
+ case FRA_GOTO:
+ case FRA_UNUSED2:
+ case FRA_PRIORITY:
+ case FRA_UNUSED3:
+ case FRA_UNUSED4:
+ case FRA_UNUSED5:
+ case FRA_FWMARK:
+ case FRA_FLOW:
+ case FRA_TABLE:
+ case FRA_FWMASK:
+ u32v = *(uint32_t *)RTA_DATA(rta);
+ zlog_debug(" %u", u32v);
+ break;
+
+ case FRA_SUPPRESS_IFGROUP:
+ case FRA_SUPPRESS_PREFIXLEN:
+ s32v = *(int32_t *)RTA_DATA(rta);
+ zlog_debug(" %d", s32v);
+ break;
+
+ case FRA_TUN_ID:
+ u64v = *(uint64_t *)RTA_DATA(rta);
+ zlog_debug(" %" PRIu64, u64v);
+ break;
+
+ case FRA_L3MDEV:
+ case FRA_PROTOCOL:
+ case FRA_IP_PROTO:
+ u8v = *(uint8_t *)RTA_DATA(rta);
+ zlog_debug(" %u", u8v);
+ break;
+
+ case FRA_UID_RANGE:
+ u_range = (struct fib_rule_uid_range *)RTA_DATA(rta);
+ if (u_range->start == u_range->end)
+ zlog_debug(" %u", u_range->start);
+ else
+ zlog_debug(" %u-%u", u_range->start, u_range->end);
+ break;
+
+ case FRA_SPORT_RANGE:
+ case FRA_DPORT_RANGE:
+ p_range = (struct fib_rule_port_range *)RTA_DATA(rta);
+ if (p_range->start == p_range->end)
+ zlog_debug(" %u", p_range->start);
+ else
+ zlog_debug(" %u-%u", p_range->start, p_range->end);
+ break;
+
+ case FRA_PAD: /* fallthrough */
+ default:
+ /* NOTHING: unhandled. */
+ break;
+ }
+
+ /* Get next pointer and start iteration again. */
+ rta = RTA_NEXT(rta, msglen);
+ goto next_rta;
+}
+
void nl_dump(void *msg, size_t msglen)
{
struct nlmsghdr *nlmsg = msg;
@@ -1120,6 +1306,7 @@ void nl_dump(void *msg, size_t msglen)
struct rtmsg *rtm;
struct nhmsg *nhm;
struct ifinfomsg *ifi;
+ struct fib_rule_hdr *frh;
char fbuf[128];
char ibuf[128];
@@ -1151,8 +1338,7 @@ next_header:
case RTM_SETLINK:
ifi = NLMSG_DATA(nlmsg);
zlog_debug(
- " ifinfomsg [family=%d type=(%d) %s "
- "index=%d flags=0x%04x {%s}]",
+ " ifinfomsg [family=%d type=(%d) %s index=%d flags=0x%04x {%s}]",
ifi->ifi_family, ifi->ifi_type,
ifi_type2str(ifi->ifi_type), ifi->ifi_index,
ifi->ifi_flags,
@@ -1170,9 +1356,7 @@ next_header:
case RTM_GETROUTE:
rtm = NLMSG_DATA(nlmsg);
zlog_debug(
- " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d "
- "table=%d protocol=(%d) %s scope=(%d) %s "
- "type=(%d) %s flags=0x%04x {%s}]",
+ " rtmsg [family=(%d) %s dstlen=%d srclen=%d tos=%d table=%d protocol=(%d) %s scope=(%d) %s type=(%d) %s flags=0x%04x {%s}]",
rtm->rtm_family, af_type2str(rtm->rtm_family),
rtm->rtm_dst_len, rtm->rtm_src_len, rtm->rtm_tos,
rtm->rtm_table, rtm->rtm_protocol,
@@ -1188,8 +1372,7 @@ next_header:
case RTM_DELNEIGH:
ndm = NLMSG_DATA(nlmsg);
zlog_debug(
- " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} "
- "flags=0x%04x {%s} type=%d (%s)]",
+ " ndm [family=%d (%s) ifindex=%d state=0x%04x {%s} flags=0x%04x {%s} type=%d (%s)]",
ndm->ndm_family, af_type2str(ndm->ndm_family),
ndm->ndm_ifindex, ndm->ndm_state,
neigh_state2str(ndm->ndm_state, ibuf, sizeof(ibuf)),
@@ -1200,12 +1383,24 @@ next_header:
nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm)));
break;
+ case RTM_NEWRULE:
+ case RTM_DELRULE:
+ frh = NLMSG_DATA(nlmsg);
+ zlog_debug(
+ " frh [family=%d (%s) dst_len=%d src_len=%d tos=%d table=%d res1=%d res2=%d action=%d (%s) flags=0x%x]",
+ frh->family, af_type2str(frh->family), frh->dst_len,
+ frh->src_len, frh->tos, frh->table, frh->res1,
+ frh->res2, frh->action, frh_action2str(frh->action),
+ frh->flags);
+ nlrule_dump(frh, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*frh)));
+ break;
+
+
case RTM_NEWADDR:
case RTM_DELADDR:
ifa = NLMSG_DATA(nlmsg);
zlog_debug(
- " ifa [family=(%d) %s prefixlen=%d "
- "flags=0x%04x {%s} scope=%d index=%u]",
+ " ifa [family=(%d) %s prefixlen=%d flags=0x%04x {%s} scope=%d index=%u]",
ifa->ifa_family, af_type2str(ifa->ifa_family),
ifa->ifa_prefixlen, ifa->ifa_flags,
if_flags2str(ifa->ifa_flags, fbuf, sizeof(fbuf)),
@@ -1218,8 +1413,7 @@ next_header:
case RTM_GETNEXTHOP:
nhm = NLMSG_DATA(nlmsg);
zlog_debug(
- " nhm [family=(%d) %s scope=(%d) %s "
- "protocol=(%d) %s flags=0x%08x {%s}]",
+ " nhm [family=(%d) %s scope=(%d) %s protocol=(%d) %s flags=0x%08x {%s}]",
nhm->nh_family, af_type2str(nhm->nh_family),
nhm->nh_scope, rtm_scope2str(nhm->nh_scope),
nhm->nh_protocol, rtm_protocol2str(nhm->nh_protocol),
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 8b30eea9f1..9b6aaf1d85 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -410,11 +410,14 @@ int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
void if_get_flags(struct interface *ifp)
{
int ret;
- struct ifreq ifreq;
+ struct ifreq ifreqflags;
+ struct ifreq ifreqdata;
- ifreq_set_name(&ifreq, ifp);
+ ifreq_set_name(&ifreqflags, ifp);
+ ifreq_set_name(&ifreqdata, ifp);
- ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq, ifp->vrf->vrf_id);
+ ret = vrf_if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreqflags,
+ ifp->vrf->vrf_id);
if (ret < 0) {
flog_err_sys(EC_LIB_SYSTEM_CALL,
"vrf_if_ioctl(SIOCGIFFLAGS %s) failed: %s",
@@ -448,8 +451,8 @@ void if_get_flags(struct interface *ifp)
struct if_data ifd = {.ifi_link_state = 0};
struct if_data *ifdata = &ifd;
- ifreq.ifr_data = (caddr_t)ifdata;
- ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreq, ifp->vrf->vrf_id);
+ ifreqdata.ifr_data = (caddr_t)ifdata;
+ ret = vrf_if_ioctl(SIOCGIFDATA, (caddr_t)&ifreqdata, ifp->vrf->vrf_id);
#endif
if (ret == -1)
@@ -459,12 +462,12 @@ void if_get_flags(struct interface *ifp)
safe_strerror(errno));
else {
if (ifdata->ifi_link_state >= LINK_STATE_UP)
- SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
else if (ifdata->ifi_link_state == LINK_STATE_UNKNOWN)
/* BSD traditionally treats UNKNOWN as UP */
- SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
else
- UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
}
#elif defined(HAVE_BSD_LINK_DETECT)
@@ -489,14 +492,14 @@ void if_get_flags(struct interface *ifp)
ifp->name, safe_strerror(errno));
} else if (ifmr.ifm_status & IFM_AVALID) { /* media state is valid */
if (ifmr.ifm_status & IFM_ACTIVE) /* media is active */
- SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ SET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
else
- UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ UNSET_FLAG(ifreqflags.ifr_flags, IFF_RUNNING);
}
#endif /* HAVE_BSD_LINK_DETECT */
out:
- if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff));
+ if_flags_update(ifp, (ifreqflags.ifr_flags & 0x0000ffff));
}
/* Set interface flags */
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index d0c86a6bb0..84c15a2a92 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -159,7 +159,17 @@ extern struct zebra_privs_t zserv_privs;
DEFINE_MTYPE_STATIC(ZEBRA, NL_BUF, "Zebra Netlink buffers");
-struct hash *nlsock_hash;
+/* Hashtable and mutex to allow lookup of nlsock structs by socket/fd value.
+ * We have both the main and dplane pthreads using these structs, so we have
+ * to protect the hash with a lock.
+ */
+static struct hash *nlsock_hash;
+pthread_mutex_t nlsock_mutex;
+
+/* Lock and unlock wrappers for nlsock hash */
+#define NLSOCK_LOCK() pthread_mutex_lock(&nlsock_mutex)
+#define NLSOCK_UNLOCK() pthread_mutex_unlock(&nlsock_mutex)
+
size_t nl_batch_tx_bufsize;
char *nl_batch_tx_buf;
@@ -1201,7 +1211,7 @@ static int nl_batch_read_resp(struct nl_batch *bth)
if (dplane_ctx_get_ns(ctx)->seq > seq)
zlog_warn(
- "%s:WARNING Recieved %u is less than any context on the queue ctx->seq %u",
+ "%s:WARNING Received %u is less than any context on the queue ctx->seq %u",
__func__, seq,
dplane_ctx_get_ns(ctx)->seq);
}
@@ -1513,11 +1523,31 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
struct nlsock *kernel_netlink_nlsock_lookup(int sock)
{
- struct nlsock lookup;
+ struct nlsock lookup, *retval;
lookup.sock = sock;
- return hash_lookup(nlsock_hash, &lookup);
+ NLSOCK_LOCK();
+ retval = hash_lookup(nlsock_hash, &lookup);
+ NLSOCK_UNLOCK();
+
+ return retval;
+}
+
+/* Insert nlsock entry into hash */
+static void kernel_netlink_nlsock_insert(struct nlsock *nls)
+{
+ NLSOCK_LOCK();
+ (void)hash_get(nlsock_hash, nls, hash_alloc_intern);
+ NLSOCK_UNLOCK();
+}
+
+/* Remove nlsock entry from hash */
+static void kernel_netlink_nlsock_remove(struct nlsock *nls)
+{
+ NLSOCK_LOCK();
+ (void)hash_release(nlsock_hash, nls);
+ NLSOCK_UNLOCK();
}
static uint32_t kernel_netlink_nlsock_key(const void *arg)
@@ -1547,11 +1577,6 @@ void kernel_init(struct zebra_ns *zns)
int one, ret;
#endif
- if (!nlsock_hash)
- nlsock_hash = hash_create_size(8, kernel_netlink_nlsock_key,
- kernel_netlink_nlsock_hash_equal,
- "Netlink Socket Hash");
-
/*
* Initialize netlink sockets
*
@@ -1584,7 +1609,8 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink.name);
exit(-1);
}
- (void)hash_get(nlsock_hash, &zns->netlink, hash_alloc_intern);
+
+ kernel_netlink_nlsock_insert(&zns->netlink);
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
@@ -1594,7 +1620,8 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_cmd.name);
exit(-1);
}
- (void)hash_get(nlsock_hash, &zns->netlink_cmd, hash_alloc_intern);
+
+ kernel_netlink_nlsock_insert(&zns->netlink_cmd);
/* Outbound socket for dplane programming of the host OS. */
snprintf(zns->netlink_dplane_out.name,
@@ -1606,8 +1633,8 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_dplane_out.name);
exit(-1);
}
- (void)hash_get(nlsock_hash, &zns->netlink_dplane_out,
- hash_alloc_intern);
+
+ kernel_netlink_nlsock_insert(&zns->netlink_dplane_out);
/* Inbound socket for OS events coming to the dplane. */
snprintf(zns->netlink_dplane_in.name,
@@ -1620,7 +1647,8 @@ void kernel_init(struct zebra_ns *zns)
zns->netlink_dplane_in.name);
exit(-1);
}
- (void)hash_get(nlsock_hash, &zns->netlink_dplane_in, hash_alloc_intern);
+
+ kernel_netlink_nlsock_insert(&zns->netlink_dplane_in);
/*
* SOL_NETLINK is not available on all platforms yet
@@ -1706,47 +1734,56 @@ void kernel_init(struct zebra_ns *zns)
rt_netlink_init();
}
+/* Helper to clean up an nlsock */
+static void kernel_nlsock_fini(struct nlsock *nls)
+{
+ if (nls && nls->sock >= 0) {
+ kernel_netlink_nlsock_remove(nls);
+ close(nls->sock);
+ nls->sock = -1;
+ XFREE(MTYPE_NL_BUF, nls->buf);
+ nls->buflen = 0;
+ }
+}
+
void kernel_terminate(struct zebra_ns *zns, bool complete)
{
thread_cancel(&zns->t_netlink);
- if (zns->netlink.sock >= 0) {
- hash_release(nlsock_hash, &zns->netlink);
- close(zns->netlink.sock);
- zns->netlink.sock = -1;
- XFREE(MTYPE_NL_BUF, zns->netlink.buf);
- zns->netlink.buflen = 0;
- }
+ kernel_nlsock_fini(&zns->netlink);
- if (zns->netlink_cmd.sock >= 0) {
- hash_release(nlsock_hash, &zns->netlink_cmd);
- close(zns->netlink_cmd.sock);
- zns->netlink_cmd.sock = -1;
- XFREE(MTYPE_NL_BUF, zns->netlink_cmd.buf);
- zns->netlink_cmd.buflen = 0;
- }
+ kernel_nlsock_fini(&zns->netlink_cmd);
- if (zns->netlink_dplane_in.sock >= 0) {
- hash_release(nlsock_hash, &zns->netlink_dplane_in);
- close(zns->netlink_dplane_in.sock);
- zns->netlink_dplane_in.sock = -1;
- XFREE(MTYPE_NL_BUF, zns->netlink_dplane_in.buf);
- zns->netlink_dplane_in.buflen = 0;
- }
+ kernel_nlsock_fini(&zns->netlink_dplane_in);
/* During zebra shutdown, we need to leave the dataplane socket
* around until all work is done.
*/
- if (complete) {
- if (zns->netlink_dplane_out.sock >= 0) {
- hash_release(nlsock_hash, &zns->netlink_dplane_out);
- close(zns->netlink_dplane_out.sock);
- zns->netlink_dplane_out.sock = -1;
- XFREE(MTYPE_NL_BUF, zns->netlink_dplane_out.buf);
- zns->netlink_dplane_out.buflen = 0;
- }
+ if (complete)
+ kernel_nlsock_fini(&zns->netlink_dplane_out);
+}
- hash_free(nlsock_hash);
- }
+/*
+ * Global init for platform-/OS-specific things
+ */
+void kernel_router_init(void)
+{
+ /* Init nlsock hash and lock */
+ pthread_mutex_init(&nlsock_mutex, NULL);
+ nlsock_hash = hash_create_size(8, kernel_netlink_nlsock_key,
+ kernel_netlink_nlsock_hash_equal,
+ "Netlink Socket Hash");
+}
+
+/*
+ * Global deinit for platform-/OS-specific things
+ */
+void kernel_router_terminate(void)
+{
+ pthread_mutex_destroy(&nlsock_mutex);
+
+ hash_free(nlsock_hash);
+ nlsock_hash = NULL;
}
+
#endif /* HAVE_NETLINK */
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 3c9d203a0b..b9228072e5 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1460,6 +1460,20 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)
}
/*
+ * Global init for platform-/OS-specific things
+ */
+void kernel_router_init(void)
+{
+}
+
+/*
+ * Global deinit for platform-/OS-specific things
+ */
+void kernel_router_terminate(void)
+{
+}
+
+/*
* Called by the dplane pthread to read incoming OS messages and dispatch them.
*/
int kernel_dplane_read(struct zebra_dplane_info *info)
diff --git a/zebra/rt.h b/zebra/rt.h
index 90148d2c0d..5e626928d9 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -78,6 +78,10 @@ extern int kernel_interface_set_master(struct interface *master,
extern int mpls_kernel_init(void);
+/* Global init and deinit for platform-/OS-specific things */
+void kernel_router_init(void);
+void kernel_router_terminate(void);
+
extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index 93c06e555b..0a79771708 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -134,6 +134,8 @@ const char *rtm_rta2str(int type);
const char *neigh_rta2str(int type);
const char *ifa_rta2str(int type);
const char *nhm_rta2str(int type);
+const char *frh_rta2str(int type);
+const char *frh_action2str(uint8_t action);
const char *nlmsg_flags2str(uint16_t flags, char *buf, size_t buflen);
const char *if_flags2str(uint32_t flags, char *buf, size_t buflen);
const char *rtm_flags2str(uint32_t flags, char *buf, size_t buflen);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 92a3b9424b..6b4a7543cd 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -262,6 +262,9 @@ void zebra_router_terminate(void)
#ifdef HAVE_SCRIPTING
zebra_script_destroy();
#endif
+
+ /* OS-specific deinit */
+ kernel_router_terminate();
}
bool zebra_router_notify_on_ack(void)
@@ -307,4 +310,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
#ifdef HAVE_SCRIPTING
zebra_script_init();
#endif
+
+ /* OS-specific init */
+ kernel_router_init();
}