return count;
}
+/* AS path loop check. If aspath contains asno
+ * that is a confed id then return >= 1.
+ */
+int aspath_loop_check_confed(struct aspath *aspath, as_t asno)
+{
+ struct assegment *seg;
+ int count = 0;
+
+ if (aspath == NULL || aspath->segments == NULL)
+ return 0;
+
+ seg = aspath->segments;
+
+ while (seg) {
+ unsigned int i;
+
+ for (i = 0; i < seg->length; i++)
+ if (seg->type != AS_CONFED_SEQUENCE &&
+ seg->type != AS_CONFED_SET && seg->as[i] == asno)
+ count++;
+
+ seg = seg->next;
+ }
+ return count;
+}
+
+
/* When all of AS path is private AS return 1. */
bool aspath_private_as_check(struct aspath *aspath)
{
extern unsigned int aspath_get_first_as(struct aspath *aspath);
extern unsigned int aspath_get_last_as(struct aspath *aspath);
extern int aspath_loop_check(struct aspath *aspath, as_t asno);
+extern int aspath_loop_check_confed(struct aspath *aspath, as_t asno);
extern bool aspath_private_as_check(struct aspath *aspath);
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn,
}
if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
+ if (STREAM_READABLE(peer->curr) <
+ BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
+ BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
+ STREAM_READABLE(peer->curr));
+ return bgp_attr_malformed(
+ args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
+
loc_block_len = stream_getc(peer->curr);
loc_node_len = stream_getc(peer->curr);
func_len = stream_getc(peer->curr);
}
if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
+ if (STREAM_READABLE(peer->curr) <
+ BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
+ BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
+ STREAM_READABLE(peer->curr));
+ return bgp_attr_malformed(
+ args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
stream_getc(peer->curr);
stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
sid_flags = stream_getc(peer->curr);
#include "bgpd/bgp_keepalives.h"
/* clang-format on */
+DEFINE_MTYPE_STATIC(BGPD, BGP_PKAT, "Peer KeepAlive Timer");
+DEFINE_MTYPE_STATIC(BGPD, BGP_COND, "BGP Peer pthread Conditional");
+DEFINE_MTYPE_STATIC(BGPD, BGP_MUTEX, "BGP Peer pthread Mutex");
+
/*
* Peer KeepAlive Timer.
* Associates a peer with the time of its last keepalive.
static struct pkat *pkat_new(struct peer *peer)
{
- struct pkat *pkat = XMALLOC(MTYPE_TMP, sizeof(struct pkat));
+ struct pkat *pkat = XMALLOC(MTYPE_BGP_PKAT, sizeof(struct pkat));
pkat->peer = peer;
monotime(&pkat->last);
return pkat;
static void pkat_del(void *pkat)
{
- XFREE(MTYPE_TMP, pkat);
+ XFREE(MTYPE_BGP_PKAT, pkat);
}
pthread_mutex_destroy(peerhash_mtx);
pthread_cond_destroy(peerhash_cond);
- XFREE(MTYPE_TMP, peerhash_mtx);
- XFREE(MTYPE_TMP, peerhash_cond);
+ XFREE(MTYPE_BGP_MUTEX, peerhash_mtx);
+ XFREE(MTYPE_BGP_COND, peerhash_cond);
}
/*
*/
rcu_read_unlock();
- peerhash_mtx = XCALLOC(MTYPE_TMP, sizeof(pthread_mutex_t));
- peerhash_cond = XCALLOC(MTYPE_TMP, sizeof(pthread_cond_t));
+ peerhash_mtx = XCALLOC(MTYPE_BGP_MUTEX, sizeof(pthread_mutex_t));
+ peerhash_cond = XCALLOC(MTYPE_BGP_COND, sizeof(pthread_cond_t));
/* initialize mutex */
pthread_mutex_init(peerhash_mtx, NULL);
/* If we're a CONFED we need to loop check the CONFED ID too */
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
- if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
+ if (aspath_loop_check_confed(piattr->aspath, bgp->confed_id)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
"%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
/* AS path loop check. */
if (do_loop_check) {
- if (aspath_loop_check(attr->aspath, bgp->as) > allowas_in ||
- (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) &&
- (aspath_loop_check(attr->aspath, bgp->confed_id) >
- allowas_in))) {
+ if (aspath_loop_check(attr->aspath, bgp->as) >
+ peer->allowas_in[afi][safi]) {
peer->stat_pfx_aspath_loop++;
reason = "as-path contains our own AS;";
goto filtered;
}
}
+ /* If we're a CONFED we need to loop check the CONFED ID too */
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) && do_loop_check)
+ if (aspath_loop_check_confed(attr->aspath, bgp->confed_id) >
+ peer->allowas_in[afi][safi]) {
+ peer->stat_pfx_aspath_loop++;
+ reason = "as-path contains our own confed AS;";
+ goto filtered;
+ }
+
/* Route reflector originator ID check. If ACCEPT_OWN mechanism is
* enabled, then take care of that too.
*/
for (i = idx_asn; i < argc; i++) {
as = strtoul(argv[i]->arg, NULL, 10);
-
- if (bgp->as == as) {
- vty_out(vty,
- "%% Local member-AS not allowed in confed peer list\n");
- continue;
- }
-
bgp_confederation_peers_add(bgp, as);
}
return CMD_SUCCESS;
struct peer *peer;
struct listnode *node, *nnode;
- if (bgp->as == as)
+ if (!bgp)
return;
if (bgp_confederation_peers_check(bgp, as))
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->as == as) {
- (void)peer_sort(peer);
peer->local_as = bgp->as;
+ (void)peer_sort(peer);
if (BGP_IS_VALID_STATE_FOR_NOTIF(
peer->status)) {
peer->last_reset =
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->as == as) {
- (void)peer_sort(peer);
peer->local_as = bgp->confed_id;
+ (void)peer_sort(peer);
if (BGP_IS_VALID_STATE_FOR_NOTIF(
peer->status)) {
peer->last_reset =
usage is printed sequentially. You can specify the daemon's name to print
only its memory usage.
+.. clicmd:: show motd
+
+ Show current motd banner.
+
.. clicmd:: show history
Dump the vtysh cli history.
higher priority to take over Master status from the existing Master. Enabled
by default.
+.. clicmd:: vrrp (1-255) checksum-with-ipv4-pseudoheader
+
+ Specify whether VRRPv3 checksum should involve IPv4 pseudoheader. This
+ command should not affect VRRPv2 and IPv6. Enabled by default.
+
.. clicmd:: vrrp (1-255) priority (1-254)
Set the router priority. The router with the highest priority is elected as
zebra
Logs communications with Zebra.
-.. clicmd:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|shutdown>
+.. clicmd:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|checksum-with-ipv4-pseudoheader|shutdown>
Configure defaults for new VRRP routers. These values will not affect
already configured VRRP routers, but will be applied to newly configured
<https://www.virtuallyghetto.com/2018/04/native-mac-learning-in-vsphere-6-7-removes-the-need-for-promiscuous-mode-for-nested-esxi.html>`_.
Issue reference: https://github.com/FRRouting/frr/issues/5386
+
+
+My router cannot interoperate with branded routers / L3 switches
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FRR includes a pseudoheader when calculating VRRPv3 checksums by default,
+regardless of whether it's IPv4 or IPv6.
+
+Some vendors have different interpretations of `VRRPv3 RFC 5798 #5.2.8
+<https://www.rfc-editor.org/rfc/rfc5798.html#section-5.2.8>`_. In such cases,
+their checksums are calculated with a pseudoheader only when it comes to IPv6.
+
+You need to disable ``checksum-with-ipv4-pseudoheader`` so that FRR computes and
+accepts such checksums.
+
+Issue reference: https://github.com/FRRouting/frr/issues/9951
iev_main_sync->ibuf.fd = -1;
control_cleanup(ctl_sock_path);
- config_clear(leconf);
#ifdef __OpenBSD__
if (sysdep.no_pfkey == 0) {
adj_del(adj, S_SHUTDOWN);
}
+ config_clear(leconf);
/* clean up */
if (iev_lde)
free(iev_lde);
#include "lib/if_clippy.c"
DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
+DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected");
DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label");
if_link_params_free(ptr);
- XFREE(MTYPE_TMP, ptr->desc);
+ XFREE(MTYPE_IFDESC, ptr->desc);
XFREE(MTYPE_IF, ptr);
*ifp = NULL;
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_IFDESC, ifp->desc);
description = yang_dnode_get_string(args->dnode, NULL);
- ifp->desc = XSTRDUP(MTYPE_TMP, description);
+ ifp->desc = XSTRDUP(MTYPE_IFDESC, description);
return NB_OK;
}
return NB_OK;
ifp = nb_running_get_entry(args->dnode, NULL, true);
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_IFDESC, ifp->desc);
return NB_OK;
}
json = json_object_new_object();
size_t header_str_sz = (2 * (end - start)) + 1;
- header_str = XMALLOC(MTYPE_TMP, header_str_sz);
+ header_str = XMALLOC(MTYPE_OSPF6_LSA_HEADER, header_str_sz);
inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
json_object_string_add(json, "header", header_str);
json_object_array_add(json_array, json);
- XFREE(MTYPE_TMP, header_str);
+ XFREE(MTYPE_OSPF6_LSA_HEADER, header_str);
} else {
vty_out(vty, "\n%s:\n", lsa->name);
#include "ospf_apiclient.h"
-/* *sigh* ... can't find a better way to hammer this into automake */
-#include "ospfd/ospf_dump_api.c"
-#include "ospfd/ospf_api.c"
-
XREF_SETUP();
DEFINE_MGROUP(OSPFCLIENT, "libospfapiclient");
ospfclient_ospfclient_LDADD = \
ospfclient/libfrrospfapiclient.la \
+ ospfd/libfrrospfclient.a \
$(LIBCAP) \
# end
#include "ospfd/ospf_ase.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_errors.h"
+#include "ospfd/ospf_memory.h"
#include "ospfd/ospf_api.h"
#include "ospfd/ospf_apiserver.h"
+DEFINE_MTYPE_STATIC(OSPFD, APISERVER, "API Server");
+DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
+
/* This is an implementation of an API to the OSPF daemon that allows
* external applications to access the OSPF daemon through socket
* connections. The application can use this API to inject its own
struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async)
{
struct ospf_apiserver *new =
- XMALLOC(MTYPE_OSPF_APISERVER, sizeof(struct ospf_apiserver));
+ XMALLOC(MTYPE_APISERVER, sizeof(struct ospf_apiserver));
- new->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER,
+ new->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER,
sizeof(struct lsa_filter_type));
new->fd_sync = fd_sync;
(void *)apiserv, apiserver_list->count);
/* And free instance. */
- XFREE(MTYPE_OSPF_APISERVER, apiserv);
+ XFREE(MTYPE_APISERVER, apiserv);
}
void ospf_apiserver_read(struct thread *thread)
connection shuts down, we can flush all LSAs of this opaque
type. */
- regtype = XCALLOC(MTYPE_OSPF_APISERVER,
- sizeof(struct registered_opaque_type));
+ regtype =
+ XCALLOC(MTYPE_APISERVER, sizeof(struct registered_opaque_type));
regtype->lsa_type = lsa_type;
regtype->opaque_type = opaque_type;
seqnum = msg_get_seq(msg);
/* Free existing filter in apiserv. */
- XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
+ XFREE(MTYPE_APISERVER_MSGFILTER, apiserv->filter);
/* Alloc new space for filter. */
size = ntohs(msg->hdr.msglen);
if (size < OSPF_MAX_LSA_SIZE) {
- apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
+ apiserv->filter = XMALLOC(MTYPE_APISERVER_MSGFILTER, size);
/* copy it over. */
memcpy(apiserv->filter, &rmsg->filter, size);
goto out;
/* send all adds based on current reachable routers */
- a = abuf = XCALLOC(MTYPE_OSPF_APISERVER,
- sizeof(struct in_addr) * rt->count);
+ a = abuf = XCALLOC(MTYPE_APISERVER, sizeof(struct in_addr) * rt->count);
for (struct route_node *rn = route_top(rt); rn; rn = route_next(rn))
if (listhead((struct list *)rn->info))
*a++ = rn->p.u.prefix4;
rc = ospf_apiserver_send_msg(apiserv, amsg);
msg_free(amsg);
}
- XFREE(MTYPE_OSPF_APISERVER, abuf);
+ XFREE(MTYPE_APISERVER, abuf);
out:
/* Send a reply back to client with return code */
return;
}
if (nrt && nrt->count)
- a = abuf = XCALLOC(MTYPE_OSPF_APISERVER, insz * nrt->count);
+ a = abuf = XCALLOC(MTYPE_APISERVER, insz * nrt->count);
if (ort && ort->count)
- d = dbuf = XCALLOC(MTYPE_OSPF_APISERVER, insz * ort->count);
+ d = dbuf = XCALLOC(MTYPE_APISERVER, insz * ort->count);
/* walk both tables */
orn = ort ? route_top(ort) : NULL;
msg_free(msg);
}
if (abuf)
- XFREE(MTYPE_OSPF_APISERVER, abuf);
+ XFREE(MTYPE_APISERVER, abuf);
if (dbuf)
- XFREE(MTYPE_OSPF_APISERVER, dbuf);
+ XFREE(MTYPE_APISERVER, dbuf);
}
#include "ospf_api.h"
#include "ospf_lsdb.h"
-/* MTYPE definition is not reflected to "memory.h". */
-#define MTYPE_OSPF_APISERVER MTYPE_TMP
-#define MTYPE_OSPF_APISERVER_MSGFILTER MTYPE_TMP
-
/* List of opaque types that application registered */
struct registered_opaque_type {
uint8_t lsa_type;
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
+DEFINE_MTYPE_STATIC(OSPFD, SNMP, "OSPF SNMP");
+
/* OSPF2-MIB. */
#define OSPF2MIB 1,3,6,1,2,1,14
static struct ospf_snmp_if *ospf_snmp_if_new(void)
{
- return XCALLOC(MTYPE_TMP, sizeof(struct ospf_snmp_if));
+ return XCALLOC(MTYPE_SNMP, sizeof(struct ospf_snmp_if));
}
static void ospf_snmp_if_free(struct ospf_snmp_if *osif)
{
- XFREE(MTYPE_TMP, osif);
+ XFREE(MTYPE_SNMP, osif);
}
static int ospf_snmp_if_delete(struct interface *ifp)
if OSPFD
noinst_LIBRARIES += ospfd/libfrrospf.a
+noinst_LIBRARIES += ospfd/libfrrospfclient.a
sbin_PROGRAMS += ospfd/ospfd
vtysh_daemons += ospfd
if SNMP
man8 += $(MANBUILD)/frr-ospfd.8
endif
+ospfd_libfrrospfclient_a_SOURCES = \
+ ospfd/ospf_api.c \
+ ospfd/ospf_dump_api.c \
+ #end
+
ospfd_libfrrospf_a_SOURCES = \
ospfd/ospf_abr.c \
ospfd/ospf_api.c \
ospfd/ospf_zebra.h \
# end
-ospfd_ospfd_LDADD = ospfd/libfrrospf.a lib/libfrr.la $(LIBCAP) $(LIBM)
+ospfd_ospfd_LDADD = ospfd/libfrrospf.a ospfd/libfrrospfclient.a lib/libfrr.la $(LIBCAP) $(LIBM)
ospfd_ospfd_SOURCES = ospfd/ospf_main.c
ospfd_ospfd_snmp_la_SOURCES = ospfd/ospf_snmp.c
--- /dev/null
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.1",
+ "defaultLocPrf":100,
+ "localAS":100,
+ "routes":{"203.0.113.0/28":[
+ {
+ "network":"203.0.113.0\/28",
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.16/28":[
+ {
+ "network":"203.0.113.16\/28",
+ "peerId":"192.0.2.2",
+ "path":"300",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.32/28":[
+ {
+ "network":"203.0.113.32\/28",
+ "peerId":"192.0.2.2",
+ "path":"300",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.48/28":[
+ {
+ "network":"203.0.113.48\/28",
+ "peerId":"192.0.2.2",
+ "path":"300 400",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.2",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
--- /dev/null
+{
+ "ipv4Unicast":{
+ "routerId":"203.0.113.1",
+ "as":100,
+ "peers":{
+ "192.0.2.2":{
+ "remoteAs": 300,
+ "state": "Established",
+ "peerState":"OK"
+ }
+ }
+ }
+}
--- /dev/null
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 100
+ no bgp ebgp-requires-policy
+!
+ neighbor 192.0.2.2 remote-as 300
+ address-family ipv4 unicast
+ network 203.0.113.0/28
+ exit-address-family
+!
--- /dev/null
+interface r1-eth0
+ ip address 192.0.2.1/28
+!
+interface lo
+ ip address 203.0.113.1/28
+!
--- /dev/null
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.17",
+ "defaultLocPrf":100,
+ "localAS":200,
+ "routes":{"203.0.113.0/28": [
+ {
+ "network":"203.0.113.0\/28",
+ "peerId":"192.0.2.1",
+ "path":"100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.16/28":[
+ {
+ "network":"203.0.113.16\/28",
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.32/28":[
+ {
+ "network":"203.0.113.32\/28",
+ "peerId":"192.0.2.18",
+ "path":"(300)",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.18",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.48/28":[
+ {
+ "network":"203.0.113.48\/28",
+ "peerId":"192.0.2.18",
+ "path":"(300) 400",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.50",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
--- /dev/null
+{
+ "ipv4Unicast":{
+ "routerId":"203.0.113.17",
+ "as":200,
+ "peers":{
+ "192.0.2.1":{
+ "remoteAs":100,
+ "state":"Established",
+ "peerState":"OK"
+ },
+ "192.0.2.18":{
+ "remoteAs":300,
+ "state":"Established",
+ "peerState":"OK"
+ }
+ }
+ }
+}
--- /dev/null
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 200
+ no bgp ebgp-requires-policy
+ bgp confederation identifier 300
+ bgp confederation peers 300
+ neighbor 192.0.2.1 remote-as 100
+ neighbor 192.0.2.18 remote-as 300
+ !
+ address-family ipv4 unicast
+ network 203.0.113.16/28
+ neighbor 192.0.2.18 default-originate
+ exit-address-family
+!
+
--- /dev/null
+interface r2-eth1
+ ip router isis 1
+ isis circuit-type level-2-only
+
+router isis 1
+ is-type level-2-only
+ net 49.0001.0002.0002.0002.00
+ redistribute ipv4 connected level-2
--- /dev/null
+interface r2-eth0
+ ip address 192.0.2.2/28
+!
+interface r2-eth1
+ ip address 192.0.2.17/28
+!
+interface lo
+ ip address 203.0.113.17/28
+!
--- /dev/null
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.33",
+ "defaultLocPrf":100,
+ "localAS":300,
+ "routes":{"0.0.0.0/0":[
+ {
+ "network":"0.0.0.0\/0",
+ "peerId":"192.0.2.17",
+ "path":"(200)",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.17",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.0/28":[
+ {
+ "network":"203.0.113.0\/28",
+ "peerId":"192.0.2.17",
+ "path":"(200) 100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.1",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.16/28":[
+ {
+ "network":"203.0.113.16\/28",
+ "peerId":"192.0.2.17",
+ "path":"(200)",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.17",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.32/28":[
+ {
+ "network":"203.0.113.32\/28",
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.48/28":[
+ {
+ "network":"203.0.113.48\/28",
+ "peerId":"192.0.2.50",
+ "path":"400",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.50",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
--- /dev/null
+{
+ "ipv4Unicast":{
+ "routerId":"203.0.113.33",
+ "as":300,
+ "peers":{
+ "192.0.2.17":{
+ "remoteAs":200,
+ "state":"Established",
+ "peerState":"OK"
+ },
+ "192.0.2.50":{
+ "remoteAs":400,
+ "state":"Established",
+ "peerState":"OK"
+ }
+ }
+ }
+}
--- /dev/null
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 300
+ no bgp ebgp-requires-policy
+ bgp confederation identifier 300
+ bgp confederation peers 200
+ neighbor 192.0.2.17 remote-as 200
+ neighbor 192.0.2.50 remote-as 400
+!
+ address-family ipv4 unicast
+ network 203.0.113.32/28
+ exit-address-family
+!
+
--- /dev/null
+interface r3-eth1
+ ip router isis 1
+ isis circuit-type level-2-only
+
+router isis 1
+ is-type level-2-only
+ net 49.0001.0003.0003.0003.00
+ redistribute ipv4 connected level-2
--- /dev/null
+!
+interface r3-eth0
+ ip address 192.0.2.49/28
+!
+interface r3-eth1
+ ip address 192.0.2.18/28
+!
+interface lo
+ ip address 203.0.113.33/28
+!
--- /dev/null
+{
+ "vrfId":0,
+ "vrfName":"default",
+ "routerId":"203.0.113.49",
+ "defaultLocPrf":100,
+ "localAS":400,
+ "routes":{"0.0.0.0/0":[
+ {
+ "network":"0.0.0.0\/0",
+ "peerId":"192.0.2.49",
+ "path":"300",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.49",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.0/28":[
+ {
+ "network":"203.0.113.0\/28",
+ "peerId":"192.0.2.49",
+ "path":"300 100",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.49",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.16/28":[
+ {
+ "network":"203.0.113.16\/28",
+ "peerId":"192.0.2.49",
+ "path":"300",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.49",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.32/28":[
+ {
+ "network":"203.0.113.32\/28",
+ "peerId":"192.0.2.49",
+ "path":"300",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"192.0.2.49",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+],"203.0.113.48/28":[
+ {
+ "network":"203.0.113.48\/28",
+ "peerId":"(unspec)",
+ "path":"",
+ "origin":"IGP",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "used":true
+ }
+ ]
+ }
+] } }
--- /dev/null
+{
+ "ipv4Unicast":{
+ "routerId":"203.0.113.49",
+ "as":400,
+ "peers":{
+ "192.0.2.49":{
+ "remoteAs":300,
+ "state":"Established",
+ "peerState":"OK"
+ }
+ }
+ }
+}
--- /dev/null
+debug bgp neighbor-events
+debug bgp nht
+debug bgp updates in
+debug bgp updates out
+!
+router bgp 400
+ no bgp ebgp-requires-policy
+ bgp disable-ebgp-connected-route-check
+!
+ neighbor 192.0.2.49 remote-as 300
+ address-family ipv4 unicast
+ network 203.0.113.48/28
+ exit-address-family
+!
--- /dev/null
+interface r4-eth0
+ ip address 192.0.2.50/28
+!
+interface lo
+ ip address 203.0.113.49/28
+!
--- /dev/null
+#!/usr/bin/env python
+
+#
+# test_bgp_confed1.py
+#
+# Copyright 2022 6WIND S.A.
+#
+# 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 6WIND DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 6WIND 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.
+#
+
+"""
+test_bgp_confed1.py: Test the FRR BGP confederations with AS member
+same as confederation Id, verify BGP prefixes and path distribution
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+def setup_module(mod):
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_convergence():
+ "Assert that BGP is converging."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for bgp peers to go up")
+
+ for router in tgen.routers().values():
+ ref_file = "{}/{}/bgp_summary.json".format(CWD, router.name)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=125, wait=2.0)
+ assertmsg = "{}: bgp did not converge".format(router.name)
+ assert res is None, assertmsg
+
+
+def test_bgp_confed_ipv4_unicast():
+ "Assert that BGP is exchanging BGP route."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for bgp peers exchanging UPDATES")
+
+ for router in tgen.routers().values():
+ ref_file = "{}/{}/bgp_ipv4_unicast.json".format(CWD, router.name)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show bgp ipv4 unicast json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=40, wait=2.5)
+ assertmsg = "{}: BGP UPDATE exchange failure".format(router.name)
+ assert res is None, assertmsg
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
vr->priority = vd.priority;
vr->preempt_mode = vd.preempt_mode;
vr->accept_mode = vd.accept_mode;
+ vr->checksum_with_ipv4_pseudoheader =
+ vd.checksum_with_ipv4_pseudoheader;
vr->shutdown = vd.shutdown;
vr->v4 = vrrp_router_create(vr, AF_INET);
pktsz = vrrp_pkt_adver_build(&pkt, &r->src, r->vr->version, r->vr->vrid,
r->priority, r->vr->advertisement_interval,
- r->addrs->count, (struct ipaddr **)&addrs);
+ r->addrs->count, (struct ipaddr **)&addrs,
+ r->vr->checksum_with_ipv4_pseudoheader);
if (DEBUG_MODE_CHECK(&vrrp_dbg_pkt, DEBUG_MODE_ALL))
zlog_hexdump(pkt, (size_t)pktsz);
zlog_hexdump(r->ibuf, nbytes);
}
- pktsize = vrrp_pkt_parse_datagram(r->family, r->vr->version, &m, nbytes,
- &src, &pkt, errbuf, sizeof(errbuf));
+ pktsize = vrrp_pkt_parse_datagram(
+ r->family, r->vr->version,
+ r->vr->checksum_with_ipv4_pseudoheader, &m, nbytes, &src, &pkt,
+ errbuf, sizeof(errbuf));
if (pktsize < 0)
DEBUGD(&vrrp_dbg_pkt,
vty_out(vty, "%svrrp default accept\n",
!vd.accept_mode ? "no " : "");
+ if (vd.checksum_with_ipv4_pseudoheader !=
+ VRRP_DEFAULT_CHECKSUM_WITH_IPV4_PSEUDOHEADER &&
+ ++writes)
+ vty_out(vty, "%svrrp default checksum-with-ipv4-pseudoheader\n",
+ !vd.checksum_with_ipv4_pseudoheader ? "no " : "");
+
if (vd.shutdown != VRRP_DEFAULT_SHUTDOWN && ++writes)
vty_out(vty, "%svrrp default shutdown\n",
!vd.shutdown ? "no " : "");
vd.preempt_mode = yang_get_default_bool("%s/preempt", VRRP_XPATH_FULL);
vd.accept_mode =
yang_get_default_bool("%s/accept-mode", VRRP_XPATH_FULL);
+ vd.checksum_with_ipv4_pseudoheader = yang_get_default_bool(
+ "%s/checksum-with-ipv4-pseudoheader", VRRP_XPATH_FULL);
vd.shutdown = VRRP_DEFAULT_SHUTDOWN;
vrrp_autoconfig_version = 3;
#define VRRP_DEFAULT_ADVINT 100
#define VRRP_DEFAULT_PREEMPT true
#define VRRP_DEFAULT_ACCEPT true
+#define VRRP_DEFAULT_CHECKSUM_WITH_IPV4_PSEUDOHEADER true
#define VRRP_DEFAULT_SHUTDOWN false
/* User compatibility constant */
uint16_t advertisement_interval;
bool preempt_mode;
bool accept_mode;
+ bool checksum_with_ipv4_pseudoheader;
bool shutdown;
};
*/
bool accept_mode;
+ /*
+ * Indicates whether this router computes and accepts VRRPv3 checksums
+ * without pseudoheader, for device interoperability.
+ *
+ * This option should only affect IPv4 virtual routers.
+ */
+ bool checksum_with_ipv4_pseudoheader;
+
struct vrrp_router *v4;
struct vrrp_router *v6;
};
return NB_OK;
}
+/*
+ * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-
+ * ipv4-pseudoheader
+ */
+static int lib_interface_vrrp_vrrp_group_checksum_with_ipv4_pseudoheader_modify(
+ struct nb_cb_modify_args *args)
+{
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ struct vrrp_vrouter *vr;
+ bool checksum_with_ipv4_ph;
+
+ vr = nb_running_get_entry(args->dnode, NULL, true);
+ checksum_with_ipv4_ph = yang_dnode_get_bool(args->dnode, NULL);
+ vr->checksum_with_ipv4_pseudoheader = checksum_with_ipv4_ph;
+
+ return NB_OK;
+}
+
/* clang-format off */
const struct frr_yang_module_info frr_vrrpd_info = {
.name = "frr-vrrpd",
.modify = lib_interface_vrrp_vrrp_group_accept_mode_modify,
}
},
+ {
+ .xpath = "/frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-ipv4-pseudoheader",
+ .cbs = {
+ .modify = lib_interface_vrrp_vrrp_group_checksum_with_ipv4_pseudoheader_modify,
+ .cli_show = cli_show_checksum_with_ipv4_pseudoheader,
+ }
+ },
{
.xpath = "/frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/advertisement-interval",
.cbs = {
* VRRP checksum in network byte order.
*/
static uint16_t vrrp_pkt_checksum(struct vrrp_pkt *pkt, size_t pktsize,
- struct ipaddr *src)
+ struct ipaddr *src, bool ipv4_ph)
{
uint16_t chksum;
bool v6 = (src->ipa_type == IPADDR_V6);
ph.next_hdr = IPPROTO_VRRP;
chksum = in_cksum_with_ph6(&ph, pkt, pktsize);
} else if (!v6 && ((pkt->hdr.vertype >> 4) == 3)) {
- struct ipv4_ph ph = {};
-
- ph.src = src->ipaddr_v4;
- inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
- ph.proto = IPPROTO_VRRP;
- ph.len = htons(pktsize);
- chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
+ if (ipv4_ph) {
+ struct ipv4_ph ph = {};
+
+ ph.src = src->ipaddr_v4;
+ inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
+ ph.proto = IPPROTO_VRRP;
+ ph.len = htons(pktsize);
+ chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
+ } else
+ chksum = in_cksum(pkt, pktsize);
} else if (!v6 && ((pkt->hdr.vertype >> 4) == 2)) {
chksum = in_cksum(pkt, pktsize);
} else {
ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
uint8_t version, uint8_t vrid, uint8_t prio,
uint16_t max_adver_int, uint8_t numip,
- struct ipaddr **ips)
+ struct ipaddr **ips, bool ipv4_ph)
{
bool v6 = false;
size_t addrsz = 0;
aptr += addrsz;
}
- (*pkt)->hdr.chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+ (*pkt)->hdr.chksum = vrrp_pkt_checksum(*pkt, pktsize, src, ipv4_ph);
return pktsize;
}
return rs;
}
-ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
- size_t read, struct ipaddr *src,
- struct vrrp_pkt **pkt, char *errmsg,
- size_t errmsg_len)
+ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph,
+ struct msghdr *m, size_t read,
+ struct ipaddr *src, struct vrrp_pkt **pkt,
+ char *errmsg, size_t errmsg_len)
{
/* Source (MAC & IP), Dest (MAC & IP) TTL validation done by kernel */
size_t addrsz = (family == AF_INET) ? sizeof(struct in_addr)
VRRP_PKT_VCHECK(pktver == version, "Bad version %u", pktver);
/* Checksum check */
- uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+ uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src, ipv4_ph);
VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum,
"Bad VRRP checksum %hx; should be %hx",
ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
uint8_t version, uint8_t vrid, uint8_t prio,
uint16_t max_adver_int, uint8_t numip,
- struct ipaddr **ips);
+ struct ipaddr **ips, bool ipv4_ph);
/* free memory allocated by vrrp_pkt_adver_build's pkt arg */
void vrrp_pkt_free(struct vrrp_pkt *pkt);
* Returns:
* Size of VRRP packet, or -1 upon error
*/
-ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
- size_t read, struct ipaddr *src,
- struct vrrp_pkt **pkt, char *errmsg,
- size_t errmsg_len);
+ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph,
+ struct msghdr *m, size_t read,
+ struct ipaddr *src, struct vrrp_pkt **pkt,
+ char *errmsg, size_t errmsg_len);
#endif /* __VRRP_PACKET_H__ */
vty_out(vty, " %svrrp %s preempt\n", pre ? "" : "no ", vrid);
}
+/*
+ * XPath: /frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group/checksum-with-
+ * ipv4-pseudoheader
+ */
+DEFPY_YANG(vrrp_checksum_with_ipv4_pseudoheader,
+ vrrp_checksum_with_ipv4_pseudoheader_cmd,
+ "[no] vrrp (1-255)$vrid checksum-with-ipv4-pseudoheader",
+ NO_STR
+ VRRP_STR
+ VRRP_VRID_STR
+ "Checksum mode in VRRPv3\n")
+{
+ nb_cli_enqueue_change(vty, "./checksum-with-ipv4-pseudoheader",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ return nb_cli_apply_changes(vty, VRRP_XPATH_ENTRY, vrid);
+}
+
+void cli_show_checksum_with_ipv4_pseudoheader(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ const char *vrid = yang_dnode_get_string(dnode, "../virtual-router-id");
+ const bool pre = yang_dnode_get_bool(dnode, NULL);
+
+ vty_out(vty, " %svrrp %s checksum-with-ipv4-pseudoheader\n",
+ pre ? "" : "no ", vrid);
+}
+
/* XXX: yang conversion */
DEFPY_YANG(vrrp_autoconfigure,
vrrp_autoconfigure_cmd,
/* XXX: yang conversion */
DEFPY_YANG(vrrp_default,
vrrp_default_cmd,
- "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|shutdown$s>",
+ "[no] vrrp default <advertisement-interval$adv (10-40950)$advint|preempt$p|priority$prio (1-254)$prioval|checksum-with-ipv4-pseudoheader$ipv4ph|shutdown$s>",
NO_STR
VRRP_STR
"Configure defaults for new VRRP instances\n"
"Preempt mode\n"
VRRP_PRIORITY_STR
"Priority value\n"
+ "Checksum mode in VRRPv3\n"
"Force VRRP router into administrative shutdown\n")
{
if (adv) {
vd.preempt_mode = !no;
if (prio)
vd.priority = no ? VRRP_DEFAULT_PRIORITY : prioval;
+ if (ipv4ph)
+ vd.checksum_with_ipv4_pseudoheader = !no;
if (s)
vd.shutdown = !no;
json_object_boolean_add(j, "shutdown", vr->shutdown);
json_object_boolean_add(j, "preemptMode", vr->preempt_mode);
json_object_boolean_add(j, "acceptMode", vr->accept_mode);
+ json_object_boolean_add(j, "checksumWithIpv4Pseudoheader",
+ vr->checksum_with_ipv4_pseudoheader);
json_object_string_add(j, "interface", vr->ifp->name);
json_object_int_add(j, "advertisementInterval",
vr->advertisement_interval * CS2MS);
vr->preempt_mode ? "Yes" : "No");
ttable_add_row(tt, "%s|%s", "Accept Mode",
vr->accept_mode ? "Yes" : "No");
+ ttable_add_row(tt, "%s|%s", "Checksum with IPv4 Pseudoheader",
+ vr->checksum_with_ipv4_pseudoheader ? "Yes" : "No");
ttable_add_row(tt, "%s|%d ms", "Advertisement Interval",
vr->advertisement_interval * CS2MS);
ttable_add_row(tt, "%s|%d ms (stale)",
install_element(INTERFACE_NODE, &vrrp_ip_cmd);
install_element(INTERFACE_NODE, &vrrp_ip6_cmd);
install_element(INTERFACE_NODE, &vrrp_preempt_cmd);
+ install_element(INTERFACE_NODE,
+ &vrrp_checksum_with_ipv4_pseudoheader_cmd);
}
bool show_defaults);
void cli_show_preempt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
+void cli_show_checksum_with_ipv4_pseudoheader(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults);
#endif /* __VRRP_VTY_H__ */
return CMD_SUCCESS;
}
+DEFUN(vtysh_motd, vtysh_motd_cmd, "show motd", SHOW_STR "Show motd\n")
+{
+ vty_hello(vty);
+ return CMD_SUCCESS;
+}
+
ALIAS(vtysh_ping, vtysh_ping_ip_cmd, "ping ip WORD",
"Send echo messages\n"
"IP echo\n"
install_element(VIEW_NODE, &no_vtysh_terminal_monitor_cmd);
install_element(VIEW_NODE, &vtysh_ping_cmd);
+ install_element(VIEW_NODE, &vtysh_motd_cmd);
install_element(VIEW_NODE, &vtysh_ping_ip_cmd);
install_element(VIEW_NODE, &vtysh_traceroute_cmd);
install_element(VIEW_NODE, &vtysh_traceroute_ip_cmd);
break;
default:
if (strncmp(line, "exit", strlen("exit")) == 0) {
- if (config)
+ if (config) {
+ if (config->exit)
+ XFREE(MTYPE_VTYSH_CONFIG_LINE,
+ config->exit);
config->exit =
XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
+ }
} else if (strncmp(line, "interface", strlen("interface")) == 0)
config = config_get(INTERFACE_NODE, line);
else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
if (!vtysh_loop_exited)
rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
+
+ free(line_read);
}
/* SIGTSTP handler. This function care user's ^Z input. */
address is not owned by the router interface";
}
+ leaf checksum-with-ipv4-pseudoheader {
+ type boolean;
+ default "true";
+ description
+ "Enabled if VRRPv3 checksum for IPv4 involves pseudoheader";
+ }
+
leaf advertisement-interval {
type uint16 {
range "1..4095";
zif->link_ifindex = link_ifindex;
if (desc) {
- XFREE(MTYPE_TMP, zif->desc);
- zif->desc = XSTRDUP(MTYPE_TMP, desc);
+ XFREE(MTYPE_ZIF_DESC, zif->desc);
+ zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
}
/* Hardware type and address. */
zif = ifp->info;
if (zif) {
- XFREE(MTYPE_TMP, zif->desc);
+ XFREE(MTYPE_ZIF_DESC, zif->desc);
if (desc)
- zif->desc = XSTRDUP(MTYPE_TMP, desc);
+ zif->desc = XSTRDUP(MTYPE_ZIF_DESC, desc);
}
} else {
/* Delete interface notification from kernel */
DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
(vty, ifp));
+DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
static void if_down_del_nbr_connected(struct interface *ifp);
if_nhg_dependents_release(ifp);
zebra_if_nhg_dependents_free(zebra_if);
- XFREE(MTYPE_TMP, zebra_if->desc);
+ XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
THREAD_OFF(zebra_if->speed_update);
#define ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zif) \
((zif)->protodown_rc == ZEBRA_PROTODOWN_EXTERNAL)
+/* Mem type for zif desc */
+DECLARE_MTYPE(ZIF_DESC);
+
/* `zebra' daemon local interface structure. */
struct zebra_if {
/* back pointer to the interface */
static struct Adv *Adv_new(void)
{
- return XCALLOC(MTYPE_TMP, sizeof(struct Adv));
+ return XCALLOC(MTYPE_IRDP_IF, sizeof(struct Adv));
}
static void Adv_free(struct Adv *adv)
{
- XFREE(MTYPE_TMP, adv);
+ XFREE(MTYPE_IRDP_IF, adv);
}
static void irdp_if_start(struct interface *ifp, int multicast,
static inline void zread_iptable(ZAPI_HANDLER_ARGS)
{
struct zebra_pbr_iptable *zpi =
- XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
+ XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_iptable));
struct stream *s;
s = msg;
#include "zebra/debug.h"
#include "zebra/zapi_msg.h"
+DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_GR, "GR");
/*
* Forward declaration.
{
struct client_gr_info *info;
- info = XCALLOC(MTYPE_TMP, sizeof(struct client_gr_info));
+ info = XCALLOC(MTYPE_ZEBRA_GR, sizeof(struct client_gr_info));
TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info);
return info;
THREAD_OFF(info->t_stale_removal);
- XFREE(MTYPE_TMP, info->current_prefix);
+ XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
LOG_GR("%s: Instance info is being deleted for client %s", __func__,
zebra_route_string(client->proto));
info->do_delete = true;
zebra_gr_delete_stale_routes(info);
- XFREE(MTYPE_TMP, info);
+ XFREE(MTYPE_ZEBRA_GR, info);
}
/*
TAILQ_INIT(&(s_client->gr_info_queue));
listnode_delete(zrouter.stale_client_list, s_client);
if (info->stale_client)
- XFREE(MTYPE_TMP, s_client);
- XFREE(MTYPE_TMP, info);
+ zserv_client_delete(s_client);
+ XFREE(MTYPE_ZEBRA_GR, info);
}
/*
/* Delete the stale client */
listnode_delete(zrouter.stale_client_list, old_client);
/* Delete old client */
- XFREE(MTYPE_TMP, old_client);
+ zserv_client_delete(old_client);
}
/*
LOG_GR("%s: Client %s all stale routes processed", __func__,
zebra_route_string(client->proto));
- XFREE(MTYPE_TMP, info->current_prefix);
+ XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
info->current_afi = 0;
zebra_gr_delete_stale_client(info);
}
&& (info->do_delete == false)) {
info->current_afi = afi;
info->current_prefix = XCALLOC(
- MTYPE_TMP,
+ MTYPE_ZEBRA_GR,
sizeof(struct prefix));
prefix_copy(
info->current_prefix,
* Reset the current prefix to indicate processing completion
* of the current AFI
*/
- XFREE(MTYPE_TMP, info->current_prefix);
+ XFREE(MTYPE_ZEBRA_GR, info->current_prefix);
}
return 0;
}
*/
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
{
- route_table_finish(zns->if_table);
+ if (zns->if_table)
+ route_table_finish(zns->if_table);
+ zns->if_table = NULL;
zebra_dplane_ns_enable(zns, false /*Disable*/);
/* definitions */
DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list");
+DEFINE_MTYPE(ZEBRA, PBR_OBJ, "PBR");
/* definitions */
static const struct message ipset_type_msg[] = {
rule = (struct zebra_pbr_rule *)arg;
(void)dplane_pbr_rule_delete(rule);
- XFREE(MTYPE_TMP, rule);
+ XFREE(MTYPE_PBR_OBJ, rule);
}
uint32_t zebra_pbr_rules_hash_key(const void *arg)
ipset = (struct zebra_pbr_ipset *)arg;
hook_call(zebra_pbr_ipset_update, 0, ipset);
- XFREE(MTYPE_TMP, ipset);
+ XFREE(MTYPE_PBR_OBJ, ipset);
}
uint32_t zebra_pbr_ipset_hash_key(const void *arg)
hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
- XFREE(MTYPE_TMP, ipset);
+ XFREE(MTYPE_PBR_OBJ, ipset);
}
uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg)
}
list_delete(&iptable->interface_name_list);
}
- XFREE(MTYPE_TMP, iptable);
+ XFREE(MTYPE_PBR_OBJ, iptable);
}
void zebra_pbr_iptable_free(void *arg)
zpr = (struct zebra_pbr_rule *)arg;
- new = XCALLOC(MTYPE_TMP, sizeof(*new));
+ new = XCALLOC(MTYPE_PBR_OBJ, sizeof(*new));
memcpy(new, zpr, sizeof(*zpr));
zebra_neigh_deref(hash_data);
hash_release(zrouter.rules_hash, hash_data);
if (free_data) {
- XFREE(MTYPE_TMP, hash_data);
+ XFREE(MTYPE_PBR_OBJ, hash_data);
return NULL;
}
(void)dplane_pbr_rule_update(found, new);
/* release the old hash data */
if (old)
- XFREE(MTYPE_TMP, old);
+ XFREE(MTYPE_PBR_OBJ, old);
} else {
if (IS_ZEBRA_DEBUG_PBR)
zlog_debug(
zpi = (struct zebra_pbr_ipset *)arg;
- new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
+ new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_ipset));
memcpy(new, zpi, sizeof(*zpi));
(void)dplane_pbr_ipset_delete(ipset);
if (lookup) {
hash_release(zrouter.ipset_hash, lookup);
- XFREE(MTYPE_TMP, lookup);
+ XFREE(MTYPE_PBR_OBJ, lookup);
} else
zlog_debug(
"%s: IPSet Entry being deleted we know nothing about",
zpi = (struct zebra_pbr_ipset_entry *)arg;
- new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
+ new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_ipset_entry));
memcpy(new, zpi, sizeof(*zpi));
(void)dplane_pbr_ipset_entry_delete(ipset);
if (lookup) {
hash_release(zrouter.ipset_entry_hash, lookup);
- XFREE(MTYPE_TMP, lookup);
+ XFREE(MTYPE_PBR_OBJ, lookup);
} else
zlog_debug("%s: IPSet being deleted we know nothing about",
__func__);
zpi = (struct zebra_pbr_iptable *)arg;
- new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
+ new = XCALLOC(MTYPE_PBR_OBJ, sizeof(struct zebra_pbr_iptable));
/* Deep structure copy */
memcpy(new, zpi, sizeof(*zpi));
node);
}
list_delete(&iptable->interface_name_list);
- XFREE(MTYPE_TMP, lookup);
+ XFREE(MTYPE_PBR_OBJ, lookup);
} else
zlog_debug("%s: IPTable being deleted we know nothing about",
__func__);
extern "C" {
#endif
+/* Memory type for PBR objects. */
+DECLARE_MTYPE(PBR_OBJ);
+
struct zebra_pbr_action {
afi_t afi;
unsigned short instance,
uint32_t session_id);
+/* Mem type for zclients. */
+DEFINE_MTYPE_STATIC(ZEBRA, ZSERV_CLIENT, "ZClients");
/*
* Client thread events.
/* Client thread lifecycle -------------------------------------------------- */
+/*
+ * Free a zserv client object.
+ */
+void zserv_client_delete(struct zserv *client)
+{
+ XFREE(MTYPE_ZSERV_CLIENT, client);
+}
+
/*
* Log zapi message to zlog.
*
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s: Deleting client %s", __func__,
zebra_route_string(client->proto));
- XFREE(MTYPE_TMP, client);
+ zserv_client_delete(client);
} else {
/* Handle cases where client has GR instance. */
if (IS_ZEBRA_DEBUG_EVENT)
int i;
afi_t afi;
- client = XCALLOC(MTYPE_TMP, sizeof(struct zserv));
+ client = XCALLOC(MTYPE_ZSERV_CLIENT, sizeof(struct zserv));
/* Make client input/output buffer. */
client->sock = sock;
*/
extern void zserv_close_client(struct zserv *client);
+/*
+ * Free memory for a zserv client object - note that this does not
+ * clean up the internal allocations associated with the zserv client,
+ * this just free the struct's memory.
+ */
+void zserv_client_delete(struct zserv *client);
+
/*
* Log a ZAPI message hexdump.
*