Merge remote-tracking branch 'upstream/master' into evpn-extended-mobility

Conflicts:
	zebra/zebra_vxlan.c
This commit is contained in:
vivek 2018-08-27 22:13:30 +00:00
commit f190902f52
101 changed files with 1593 additions and 3533 deletions

View File

@ -4896,6 +4896,23 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
}
/*
* Lookup L3-VNI
*/
bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni)
{
struct list *inst = bm->bgp;
struct listnode *node;
struct bgp *bgp_vrf;
for (ALL_LIST_ELEMENTS_RO(inst, node, bgp_vrf)) {
if (bgp_vrf->l3vni == vni)
return true;
}
return false;
}
/*
* Lookup VNI.
*/

View File

@ -503,4 +503,5 @@ extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi);
extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi,
struct ipaddr *originator_ip);
extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es);
extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
#endif /* _BGP_EVPN_PRIVATE_H */

View File

@ -1888,6 +1888,14 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
vpn = bgp_evpn_lookup_vni(bgp, vni);
if (!vpn) {
/* Check if this L2VNI is already configured as L3VNI */
if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
flog_err(BGP_ERR_VNI,
"%u: Failed to create L2VNI %u, it is configured as L3VNI",
bgp->vrf_id, vni);
return NULL;
}
/* tenant vrf will be updated when we get local_vni_add from
* zebra
*/

View File

@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
if (BGP_DEBUG(flowspec, FLOWSPEC)) {
char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX * 2];
char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX*2+16];
char ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
char *s = NULL;

View File

@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
struct listnode *node;
struct bgp_pbr_match_entry *bpme;
struct bgp_pbr_match *bpm;
int unit = 0;
bool list_began = false;
struct list *list_bpm;
list_bpm = list_new();
@ -347,14 +347,14 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
if (listnode_lookup(list_bpm, bpm))
continue;
listnode_add(list_bpm, bpm);
if (unit == 0)
if (!list_began) {
vty_out(vty, " (");
else
list_began = true;
} else
vty_out(vty, ", ");
vty_out(vty, "%s", bpm->ipset_name);
unit++;
}
if (unit)
if (list_began)
vty_out(vty, ")");
vty_out(vty, "\n");
list_delete_and_null(&list_bpm);

View File

@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
listener->fd = sock;
/* this socket needs a change of ns. record bgp back pointer */
if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(
vrf_lookup_by_id(bgp->vrf_id)))
listener->bgp = bgp;
memcpy(&listener->su, sa, salen);

View File

@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
? "!" : "",
bpf->dscp->val);
}
zlog_info("BGP: %s FS PBR from %s to %s, %s %s",
zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
add ? "adding" : "removing",
bpf->src == NULL ? "<all>" :
prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
@ -1807,7 +1807,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
bgp_pbr_match_alloc_intern);
/* new, then self allocate ipset_name and unique */
if (bpm && bpm->unique == 0) {
if (bpm->unique == 0) {
bpm->unique = ++bgp_pbr_match_counter_unique;
/* 0 value is forbidden */
sprintf(bpm->ipset_name, "match%p", bpm);
@ -1838,10 +1838,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
temp2.src_port_max = src_port ? src_port->max_port : 0;
temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
temp2.proto = bpf->protocol;
if (bpm)
bpme = hash_get(bpm->entry_hash, &temp2,
bgp_pbr_match_entry_alloc_intern);
if (bpme && bpme->unique == 0) {
bpme = hash_get(bpm->entry_hash, &temp2,
bgp_pbr_match_entry_alloc_intern);
if (bpme->unique == 0) {
bpme->unique = ++bgp_pbr_match_entry_counter_unique;
/* 0 value is forbidden */
bpme->backpointer = bpm;
@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
bpme_found = true;
/* already installed */
if (bpme_found && bpme) {
if (bpme_found) {
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
if (extra && extra->bgp_fs_pbr &&

View File

@ -38,6 +38,7 @@
#include "queue.h"
#include "memory.h"
#include "lib/json.h"
#include "lib_errors.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@ -188,8 +189,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
if (e->parent) {
struct bgp_info *bi = (struct bgp_info *)e->parent;
if (bi->net)
bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
if (bi->net) {
/* FIXME: since multiple e may have the same e->parent
* and e->parent->net is holding a refcount for each
* of them, we need to do some fudging here.
*
* WARNING: if bi->net->lock drops to 0, bi may be
* freed as well (because bi->net was holding the
* last reference to bi) => write after free!
*/
unsigned refcount;
bi = bgp_info_lock(bi);
refcount = bi->net->lock - 1;
bgp_unlock_node((struct bgp_node *)bi->net);
if (!refcount)
bi->net = NULL;
bgp_info_unlock(bi);
}
bgp_info_unlock(e->parent);
e->parent = NULL;
}
@ -198,8 +215,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
bgp_unlock(e->bgp_orig);
if ((*extra)->bgp_fs_pbr)
list_delete_all_node((*extra)->bgp_fs_pbr);
(*extra)->bgp_fs_pbr = NULL;
list_delete_and_null(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
*extra = NULL;
@ -338,14 +354,9 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
/* slight hack, but more robust against errors. */
if (ri->peer->pcount[table->afi][table->safi])
ri->peer->pcount[table->afi][table->safi]--;
else {
zlog_warn(
"%s: Asked to decrement 0 prefix count for peer %s",
__func__, ri->peer->host);
zlog_backtrace(LOG_WARNING);
zlog_warn("%s: Please report to Quagga bugzilla",
__func__);
}
else
flog_err(LIB_ERR_DEVELOPMENT,
"Asked to decrement 0 prefix count for peer");
} else if (BGP_INFO_COUNTABLE(ri)
&& !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
SET_FLAG(ri->flags, BGP_INFO_COUNTED);
@ -1039,8 +1050,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
#define FILTER_EXIST_WARN(F, f, filter) \
if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
zlog_warn("%s: Could not find configured input %s-list %s!", \
peer->host, #f, F##_IN_NAME(filter));
zlog_debug("%s: Could not find configured input %s-list %s!", \
peer->host, #f, F##_IN_NAME(filter));
if (DISTRIBUTE_IN_NAME(filter)) {
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@ -1078,8 +1089,8 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
#define FILTER_EXIST_WARN(F, f, filter) \
if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
zlog_warn("%s: Could not find configured output %s-list %s!", \
peer->host, #f, F##_OUT_NAME(filter));
zlog_debug("%s: Could not find configured output %s-list %s!", \
peer->host, #f, F##_OUT_NAME(filter));
if (DISTRIBUTE_OUT_NAME(filter)) {
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@ -8187,7 +8198,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
vty_out(vty, " \"routeDistinguishers\" : {");
++*json_header_depth;
}
json_paths = json_object_new_object();
}
if (use_json && rd) {
@ -8414,8 +8424,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
*total_cum = total_count;
}
if (use_json) {
if (json_paths)
json_object_free(json_paths);
if (rd) {
vty_out(vty, " }%s ", (is_last ? "" : ","));
}
@ -8573,9 +8581,19 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
int count = 0;
int best = 0;
int suppress = 0;
int accept_own = 0;
int route_filter_translated_v4 = 0;
int route_filter_v4 = 0;
int route_filter_translated_v6 = 0;
int route_filter_v6 = 0;
int llgr_stale = 0;
int no_llgr = 0;
int accept_own_nexthop = 0;
int blackhole = 0;
int no_export = 0;
int no_advertise = 0;
int local_as = 0;
int no_peer = 0;
int first = 1;
int has_valid_label = 0;
mpls_label_t label = 0;
@ -8652,12 +8670,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
} else
vty_out(vty, ", no best path");
if (no_advertise)
vty_out(vty, ", not advertised to any peer");
if (accept_own)
vty_out(vty,
", accept own local route exported and imported in different VRF");
else if (route_filter_translated_v4)
vty_out(vty,
", mark translated RTs for VPNv4 route filtering");
else if (route_filter_v4)
vty_out(vty,
", attach RT as-is for VPNv4 route filtering");
else if (route_filter_translated_v6)
vty_out(vty,
", mark translated RTs for VPNv6 route filtering");
else if (route_filter_v6)
vty_out(vty,
", attach RT as-is for VPNv6 route filtering");
else if (llgr_stale)
vty_out(vty,
", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
else if (no_llgr)
vty_out(vty,
", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
else if (accept_own_nexthop)
vty_out(vty,
", accept local nexthop");
else if (blackhole)
vty_out(vty, ", inform peer to blackhole prefix");
else if (no_export)
vty_out(vty, ", not advertised to EBGP peer");
else if (no_advertise)
vty_out(vty, ", not advertised to any peer");
else if (local_as)
vty_out(vty, ", not advertised outside local AS");
else if (no_peer)
vty_out(vty,
", inform EBGP peer not to advertise to their EBGP peers");
if (suppress)
vty_out(vty,
@ -9018,6 +9065,10 @@ DEFUN (show_ip_bgp,
|prefix-list WORD\
|filter-list WORD\
|statistics\
|community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
route-filter-v6|route-filter-v4|route-filter-translated-v6|\
route-filter-translated-v4> [exact-match]\
|community-list <(1-500)|WORD> [exact-match]\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
@ -9037,6 +9088,23 @@ DEFUN (show_ip_bgp,
"Display routes conforming to the filter-list\n"
"Regular expression access list name\n"
"BGP RIB advertisement statistics\n"
"Display routes matching the communities\n"
COMMUNITY_AANN_STR
"Do not send outside local AS (well-known community)\n"
"Do not advertise to any peer (well-known community)\n"
"Do not export to next AS (well-known community)\n"
"Graceful shutdown (well-known community)\n"
"Do not export to any peer (well-known community)\n"
"Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
"Staled Long-lived Graceful Restart VPN route (well-known community)\n"
"Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
"Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
"Should accept VPN route with local nexthop (well-known community)\n"
"RT VPNv6 route filtering (well-known community)\n"
"RT VPNv4 route filtering (well-known community)\n"
"RT translated VPNv6 route filtering (well-known community)\n"
"RT translated VPNv4 route filtering (well-known community)\n"
"Exact match of the communities\n"
"Display routes matching the community-list\n"
"community-list number\n"
"community-list name\n"
@ -9797,8 +9865,6 @@ static int bgp_peer_count_walker(struct thread *t)
pc->count[PCOUNT_ADJ_IN]++;
for (ri = rn->info; ri; ri = ri->next) {
char buf[SU_ADDRSTRLEN];
if (ri->peer != peer)
continue;
@ -9820,22 +9886,12 @@ static int bgp_peer_count_walker(struct thread *t)
if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
pc->count[PCOUNT_COUNTED]++;
if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
zlog_warn(
"%s [pcount] %s/%d is counted but flags 0x%x",
peer->host,
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
SU_ADDRSTRLEN),
rn->p.prefixlen, ri->flags);
flog_err(LIB_ERR_DEVELOPMENT,
"Attempting to count but flags say it is unusable");
} else {
if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
zlog_warn(
"%s [pcount] %s/%d not counted but flags 0x%x",
peer->host,
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
SU_ADDRSTRLEN),
rn->p.prefixlen, ri->flags);
flog_err(LIB_ERR_DEVELOPMENT,
"Not counted but flags say we should");
}
}
}

View File

@ -47,6 +47,7 @@
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_route.h"
#include "lib/network.h"
#include "lib/thread.h"
#include "rtrlib/rtrlib.h"
#include "rtrlib/rtr_mgr.h"
@ -131,12 +132,14 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix,
static void *route_match_compile(const char *arg);
static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
safi_t safi);
static void revalidate_all_routes(void);
static struct rtr_mgr_config *rtr_config;
static struct list *cache_list;
static int rtr_is_running;
static int rtr_is_stopping;
static int rtr_is_starting;
static _Atomic int rtr_update_overflow;
static int rpki_debug;
static unsigned int polling_period;
static unsigned int expire_interval;
@ -229,7 +232,7 @@ static void *route_match_compile(const char *arg)
{
int *rpki_status;
rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
if (strcmp(arg, "valid") == 0)
*rpki_status = RPKI_VALID;
@ -345,6 +348,19 @@ static int bgpd_sync_callback(struct thread *thread)
thread_add_read(bm->master, bgpd_sync_callback, NULL,
rpki_sync_socket_bgpd, NULL);
if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
while (read(rpki_sync_socket_bgpd, &rec,
sizeof(struct pfx_record))
!= -1)
;
atomic_store_explicit(&rtr_update_overflow, 0,
memory_order_seq_cst);
revalidate_all_routes();
return 0;
}
int retval =
read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
if (retval != sizeof(struct pfx_record)) {
@ -356,26 +372,36 @@ static int bgpd_sync_callback(struct thread *thread)
afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
safi_t safi;
struct peer *peer;
struct listnode *peer_listnode;
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
if (!bgp->rib[afi][safi])
continue;
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
safi_t safi;
struct list *matches = list_new();
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
if (!peer->bgp->rib[afi][safi])
continue;
matches->del = (void (*)(void *))bgp_unlock_node;
struct list *matches = list_new();
bgp_table_range_lookup(bgp->rib[afi][safi], prefix,
rec.max_len, matches);
matches->del =
(void (*)(void *))bgp_unlock_node;
bgp_table_range_lookup(
peer->bgp->rib[afi][safi], prefix,
rec.max_len, matches);
struct bgp_node *bgp_node;
struct bgp_node *bgp_node;
struct listnode *bgp_listnode;
for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node))
revalidate_bgp_node(bgp_node, afi, safi);
for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
bgp_node))
revalidate_bgp_node(bgp_node, afi,
safi);
list_delete_and_null(&matches);
list_delete_and_null(&matches);
}
}
}
@ -398,14 +424,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
label = bgp_info->extra->label;
num_labels = bgp_info->extra->num_labels;
}
ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi,
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
label, num_labels, 1, NULL);
ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id,
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, NULL, label, num_labels, 1,
NULL);
if (ret < 0) {
bgp_unlock_node(bgp_node);
if (ret < 0)
return;
}
}
}
@ -413,25 +438,23 @@ static void revalidate_all_routes(void)
{
struct bgp *bgp;
struct listnode *node;
struct bgp_node *bgp_node;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
for (size_t i = 0; i < 2; i++) {
safi_t safi;
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
struct peer *peer;
struct listnode *peer_listnode;
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
if (!bgp->rib[afi][safi])
continue;
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
for (bgp_node =
bgp_table_top(bgp->rib[afi][safi]);
bgp_node;
bgp_node = bgp_route_next(bgp_node)) {
if (bgp_node->info != NULL) {
revalidate_bgp_node(bgp_node,
afi, safi);
}
for (size_t i = 0; i < 2; i++) {
safi_t safi;
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
for (safi = SAFI_UNICAST; safi < SAFI_MAX;
safi++) {
if (!peer->bgp->rib[afi][safi])
continue;
bgp_soft_reconfig_in(peer, afi, safi);
}
}
}
@ -442,28 +465,53 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
const struct pfx_record rec,
const bool added __attribute__((unused)))
{
if (rtr_is_stopping || rtr_is_starting)
if (rtr_is_stopping || rtr_is_starting
|| atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
return;
int retval =
write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
if (retval != sizeof(struct pfx_record))
if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
atomic_store_explicit(&rtr_update_overflow, 1,
memory_order_seq_cst);
else if (retval != sizeof(struct pfx_record))
RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
}
static void rpki_init_sync_socket(void)
{
int fds[2];
const char *msg;
RPKI_DEBUG("initializing sync socket");
if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
RPKI_DEBUG("Could not open rpki sync socket");
return;
msg = "could not open rpki sync socketpair";
goto err;
}
rpki_sync_socket_rtr = fds[0];
rpki_sync_socket_bgpd = fds[1];
if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
msg = "could not set rpki_sync_socket_rtr to non blocking";
goto err;
}
if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
msg = "could not set rpki_sync_socket_bgpd to non blocking";
goto err;
}
thread_add_read(bm->master, bgpd_sync_callback, NULL,
rpki_sync_socket_bgpd, NULL);
return;
err:
zlog_err("RPKI: %s", msg);
abort();
}
static int bgp_rpki_init(struct thread_master *master)
@ -514,6 +562,7 @@ static int start(void)
rtr_is_stopping = 0;
rtr_is_starting = 1;
rtr_update_overflow = 0;
if (list_isempty(cache_list)) {
RPKI_DEBUG(
@ -1210,10 +1259,10 @@ DEFUN_NOSH (rpki_exit,
"exit",
"Exit rpki configuration and restart rpki session\n")
{
int ret = reset(false);
reset(false);
vty->node = CONFIG_NODE;
return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
return CMD_SUCCESS;
}
DEFUN_NOSH (rpki_quit,

View File

@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
/*
* bgp_unlock_node
*/
static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node)
static inline void bgp_unlock_node(struct bgp_node *node)
{
return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node));
route_unlock_node(bgp_node_to_rnode(node));
}
/*

View File

@ -2019,7 +2019,7 @@ DEFUN (no_bgp_fast_external_failover,
}
/* "bgp enforce-first-as" configuration. */
#if CONFDATE > 20180517
#if CONFDATE > 20190517
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
#endif
@ -10995,7 +10995,7 @@ DEFUN (show_ip_bgp_attr_info,
}
static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
afi_t afi, safi_t safi)
afi_t afi, safi_t safi, uint8_t use_json)
{
struct bgp *bgp;
struct listnode *node;
@ -11004,64 +11004,148 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
char *ecom_str;
vpn_policy_direction_t dir;
if (name) {
bgp = bgp_lookup_by_name(name);
if (use_json) {
json_object *json = NULL;
json_object *json_import_vrfs = NULL;
json_object *json_export_vrfs = NULL;
json = json_object_new_object();
/* Provide context for the block */
json_object_string_add(json, "vrf", name ? name : "default");
json_object_string_add(json, "afiSafi",
afi_safi_print(afi, safi));
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) {
json_object_boolean_true_add(json,
"bgpNoSuchInstance");
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json,
JSON_C_TO_STRING_PRETTY));
json_object_free(json);
return CMD_WARNING;
}
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
json_object_string_add(json, "importFromVrfs", "none");
json_object_string_add(json, "importRts", "none");
} else {
json_import_vrfs = json_object_new_array();
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].import_vrf,
node, vname))
json_object_array_add(json_import_vrfs,
json_object_new_string(vname));
dir = BGP_VPN_POLICY_DIR_FROMVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
json_object_object_add(json, "importFromVrfs",
json_import_vrfs);
json_object_string_add(json, "importRts", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
json_object_string_add(json, "exportToVrfs", "none");
json_object_string_add(json, "routeDistinguisher",
"none");
json_object_string_add(json, "exportRts", "none");
} else {
json_export_vrfs = json_object_new_array();
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].export_vrf,
node, vname))
json_object_array_add(json_export_vrfs,
json_object_new_string(vname));
json_object_object_add(json, "exportToVrfs",
json_export_vrfs);
json_object_string_add(json, "routeDistinguisher",
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
buf1, RD_ADDRSTRLEN));
dir = BGP_VPN_POLICY_DIR_TOVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
json_object_string_add(json, "exportRts", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
vty_out(vty, "%s\n",
json_object_to_json_string_ext(json,
JSON_C_TO_STRING_PRETTY));
json_object_free(json);
} else {
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) {
vty_out(vty, "%% No such BGP instance exist\n");
return CMD_WARNING;
}
} else {
bgp = bgp_get_default();
if (!bgp) {
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT))
vty_out(vty,
"%% Default BGP instance does not exist\n");
return CMD_WARNING;
}
}
"This VRF is not importing %s routes from any other VRF\n",
afi_safi_print(afi, safi));
else {
vty_out(vty,
"This VRF is importing %s routes from the following VRFs:\n",
afi_safi_print(afi, safi));
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
vty_out(vty,
"This VRF is not importing %s routes from any other VRF\n",
afi_safi_print(afi, safi));
} else {
vty_out(vty,
"This VRF is importing %s routes from the following VRFs:\n",
afi_safi_print(afi, safi));
for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
vname)) {
vty_out(vty, " %s\n", vname);
}
dir = BGP_VPN_POLICY_DIR_FROMVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out(vty, "Import RT(s): %s\n", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].import_vrf,
node, vname))
vty_out(vty, " %s\n", vname);
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
vty_out(vty,
"This VRF is not exporting %s routes to any other VRF\n",
afi_safi_print(afi, safi));
} else {
vty_out(vty,
"This VRF is exporting %s routes to the following VRFs:\n",
afi_safi_print(afi, safi));
for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].export_vrf, node,
vname)) {
vty_out(vty, " %s\n", vname);
dir = BGP_VPN_POLICY_DIR_FROMVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out(vty, "Import RT(s): %s\n", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_EXPORT))
vty_out(vty,
"This VRF is not exporting %s routes to any other VRF\n",
afi_safi_print(afi, safi));
else {
vty_out(vty,
"This VRF is exporting %s routes to the following VRFs:\n",
afi_safi_print(afi, safi));
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].export_vrf,
node, vname))
vty_out(vty, " %s\n", vname);
vty_out(vty, "RD: %s\n",
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
buf1, RD_ADDRSTRLEN));
dir = BGP_VPN_POLICY_DIR_TOVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out(vty, "Export RT: %s\n", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
vty_out(vty, "RD: %s\n",
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
buf1, RD_ADDRSTRLEN));
dir = BGP_VPN_POLICY_DIR_TOVPN;
ecom_str = ecommunity_ecom2str(
bgp->vpn_policy[afi].rtlist[dir],
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
vty_out(vty, "Emport RT: %s\n", ecom_str);
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
return CMD_SUCCESS;
@ -11069,20 +11153,22 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
/* "show [ip] bgp route-leak" command. */
DEFUN (show_ip_bgp_route_leak,
show_ip_bgp_route_leak_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_HELP_STR
"Route leaking information\n")
show_ip_bgp_route_leak_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_HELP_STR
"Route leaking information\n"
JSON_STR)
{
char *vrf = NULL;
afi_t afi = AFI_MAX;
safi_t safi = SAFI_MAX;
uint8_t uj = use_json(argc, argv);
int idx = 0;
/* show [ip] bgp */
@ -11110,7 +11196,7 @@ DEFUN (show_ip_bgp_route_leak,
return CMD_WARNING;
}
return bgp_show_route_leak_vty(vty, vrf, afi, safi);
return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj);
}
static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
@ -11462,7 +11548,7 @@ DEFUN (bgp_redistribute_ipv4,
}
bgp_redist_add(bgp, AFI_IP, type, 0);
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
return bgp_redistribute_set(bgp, AFI_IP, type, 0, false);
}
ALIAS_HIDDEN(
@ -11483,6 +11569,7 @@ DEFUN (bgp_redistribute_ipv4_rmap,
int idx_word = 3;
int type;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
if (type < 0) {
@ -11491,8 +11578,8 @@ DEFUN (bgp_redistribute_ipv4_rmap,
}
red = bgp_redist_add(bgp, AFI_IP, type, 0);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
}
ALIAS_HIDDEN(
@ -11516,6 +11603,7 @@ DEFUN (bgp_redistribute_ipv4_metric,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
if (type < 0) {
@ -11525,8 +11613,8 @@ DEFUN (bgp_redistribute_ipv4_metric,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, type, 0);
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
}
ALIAS_HIDDEN(
@ -11553,6 +11641,7 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
if (type < 0) {
@ -11562,9 +11651,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, type, 0);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
}
ALIAS_HIDDEN(
@ -11595,6 +11684,7 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
if (type < 0) {
@ -11604,9 +11694,9 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, type, 0);
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
}
ALIAS_HIDDEN(
@ -11642,7 +11732,7 @@ DEFUN (bgp_redistribute_ipv4_ospf,
protocol = ZEBRA_ROUTE_TABLE;
bgp_redist_add(bgp, AFI_IP, protocol, instance);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, false);
}
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd,
@ -11669,6 +11759,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
struct bgp_redist *red;
unsigned short instance;
int protocol;
bool changed;
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
@ -11677,8 +11768,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
instance = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
}
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
@ -11709,6 +11800,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
struct bgp_redist *red;
unsigned short instance;
int protocol;
bool changed;
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
@ -11719,8 +11811,9 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
metric);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
}
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
@ -11754,6 +11847,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
struct bgp_redist *red;
unsigned short instance;
int protocol;
bool changed;
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
@ -11764,9 +11858,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
metric);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
}
ALIAS_HIDDEN(
@ -11803,6 +11898,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
struct bgp_redist *red;
unsigned short instance;
int protocol;
bool changed;
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
protocol = ZEBRA_ROUTE_OSPF;
@ -11813,9 +11909,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
metric);
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
}
ALIAS_HIDDEN(
@ -11923,7 +12020,7 @@ DEFUN (bgp_redistribute_ipv6,
}
bgp_redist_add(bgp, AFI_IP6, type, 0);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, false);
}
DEFUN (bgp_redistribute_ipv6_rmap,
@ -11939,6 +12036,7 @@ DEFUN (bgp_redistribute_ipv6_rmap,
int idx_word = 3;
int type;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
if (type < 0) {
@ -11947,8 +12045,8 @@ DEFUN (bgp_redistribute_ipv6_rmap,
}
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
DEFUN (bgp_redistribute_ipv6_metric,
@ -11965,6 +12063,7 @@ DEFUN (bgp_redistribute_ipv6_metric,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
if (type < 0) {
@ -11974,8 +12073,8 @@ DEFUN (bgp_redistribute_ipv6_metric,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
DEFUN (bgp_redistribute_ipv6_rmap_metric,
@ -11995,6 +12094,7 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
if (type < 0) {
@ -12004,9 +12104,10 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type,
metric);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
DEFUN (bgp_redistribute_ipv6_metric_rmap,
@ -12026,6 +12127,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
int type;
uint32_t metric;
struct bgp_redist *red;
bool changed;
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
if (type < 0) {
@ -12035,9 +12137,10 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
metric = strtoul(argv[idx_number]->arg, NULL, 10);
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric);
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST,
metric);
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
DEFUN (no_bgp_redistribute_ipv6,

View File

@ -1576,8 +1576,14 @@ static void bgp_redist_del(struct bgp *bgp, afi_t afi, uint8_t type,
/* Other routes redistribution into BGP. */
int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
unsigned short instance)
unsigned short instance, bool changed)
{
/* If redistribute options are changed call
* bgp_redistribute_unreg() to reset the option and withdraw
* the routes
*/
if (changed)
bgp_redistribute_unreg(bgp, afi, type, instance);
/* Return if already redistribute flag is set. */
if (instance) {

View File

@ -51,7 +51,8 @@ extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t,
unsigned short);
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
unsigned short);
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short);
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short,
bool changed);
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short);
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,

View File

@ -3187,15 +3187,16 @@ int bgp_delete(struct bgp *bgp)
.import_redirect_rtlist);
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
}
/* Remove visibility via the master list - there may however still be
* routes to be processed still referencing the struct bgp.
*/
listnode_delete(bm->bgp, bgp);
/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
bgp_zebra_instance_deregister(bgp);
/* Remove visibility via the master list - there may however still be
* routes to be processed still referencing the struct bgp.
*/
listnode_delete(bm->bgp, bgp);
/* Free interfaces in this instance. */
bgp_if_finish(bgp);
@ -6631,17 +6632,6 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json,
time_t uptime1, epoch_tbuf;
struct tm *tm;
/* Check buffer length. */
if (len < BGP_UPTIME_LEN) {
if (!use_json) {
zlog_warn("peer_uptime (): buffer shortage %lu",
(unsigned long)len);
/* XXX: should return status instead of buf... */
snprintf(buf, len, "<error> ");
}
return buf;
}
/* If there is no connection has been done before print `never'. */
if (uptime2 == 0) {
if (use_json) {
@ -7356,7 +7346,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
}
/* clang-format off */
#if CONFDATE > 20180517
#if CONFDATE > 20190517
CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
#endif
/* clang-format on */

View File

@ -382,7 +382,7 @@ AC_ARG_ENABLE(bgp-vnc,
AC_ARG_WITH(rfp-path,
AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
AC_ARG_ENABLE(snmp,
AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)]))
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
AC_ARG_ENABLE(zeromq,
AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
AC_ARG_WITH(libpam,
@ -418,8 +418,6 @@ AC_ARG_ENABLE(rusage,
AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
AC_ARG_ENABLE(gcc_ultra_verbose,
AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings]))
AC_ARG_ENABLE(linux24_tcp_md5,
AS_HELP_STRING([--enable-linux24-tcp-md5], [enable support for old, Linux-2.4 RFC2385 patch]))
AC_ARG_ENABLE(backtrace,
AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
AC_ARG_ENABLE(time-check,
@ -644,10 +642,6 @@ AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
# End of logic for protobuf support.
#
if test "${enable_linux24_tcp_md5}" = "yes"; then
AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch)
fi
AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements)
if test "${enable_rtadv}" != "no"; then
AC_MSG_RESULT(yes)
@ -1496,14 +1490,13 @@ int main(void);
yes)
SNMP_METHOD=agentx
;;
smux|agentx)
agentx)
SNMP_METHOD="${enable_snmp}"
;;
*)
AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use smux or agentx])
AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use yes or agentx])
;;
esac
AH_TEMPLATE([SNMP_SMUX], [Use SNMP SMUX to interface with snmpd])
AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd])
AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
fi

View File

@ -10,7 +10,6 @@
WANT_LDP ?= 1
WANT_PIM ?= 1
WANT_OSPFAPI ?= 1
WANT_TCP_ZEBRA ?= 0
WANT_BGP_VNC ?= 1
WANT_CUMULUS_MODE ?= 0
WANT_MULTIPATH ?= 1
@ -65,12 +64,6 @@ else
USE_OSPFAPI=--enable-ospfapi=no
endif
ifeq ($(WANT_TCP_ZEBRA),1)
USE_TCP_ZEBRA=--enable-tcp-zebra
else
USE_TCP_ZEBRA=--disable-tcp-zebra
endif
ifeq ($(WANT_BGP_VNC), 1)
USE_BGP_VNC=--enable-bgp-vnc=yes
else
@ -123,7 +116,6 @@ override_dh_auto_configure:
$(USE_OSPFAPI) \
$(USE_MULTIPATH) \
$(USE_LDP) \
$(USE_TCP_ZEBRA) \
--enable-fpm \
$(USE_FRR_USER) $(USE_FRR_GROUP) \
$(USE_FRR_VTY_GROUP) \
@ -162,12 +154,8 @@ override_dh_auto_install:
mkdir -p debian/tmp/etc/frr/
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
# installing the Frr specific SNMP MIB
ifeq ($(WANT_SNMP), 1)
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
else
# leftover from previously shipping SMUX client OID MIB
mkdir -p debian/tmp/usr/share/snmp/mibs
endif
# cleaning .la files
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la

View File

@ -10,7 +10,6 @@
WANT_LDP ?= 1
WANT_PIM ?= 1
WANT_OSPFAPI ?= 1
WANT_TCP_ZEBRA ?= 0
WANT_BGP_VNC ?= 1
WANT_CUMULUS_MODE ?= 0
WANT_MULTIPATH ?= 1
@ -75,12 +74,6 @@ else
USE_OSPFAPI=--enable-ospfapi=no
endif
ifeq ($(WANT_TCP_ZEBRA),1)
USE_TCP_ZEBRA=--enable-tcp-zebra
else
USE_TCP_ZEBRA=--disable-tcp-zebra
endif
ifeq ($(WANT_BGP_VNC), 1)
USE_BGP_VNC=--enable-bgp-vnc=yes
else
@ -152,7 +145,6 @@ override_dh_auto_configure:
$(USE_OSPFAPI) \
$(USE_MULTIPATH) \
$(USE_LDP) \
$(USE_TCP_ZEBRA) \
--enable-fpm \
$(USE_FRR_USER) $(USE_FRR_GROUP) \
$(USE_FRR_VTY_GROUP) \
@ -196,12 +188,8 @@ override_dh_auto_install:
mkdir -p debian/tmp/etc/frr/
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
# installing the Frr specific SNMP MIB
ifeq ($(WANT_SNMP), 1)
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
else
# leftover from previously shipping SMUX client OID MIB
mkdir -p debian/tmp/usr/share/snmp/mibs/
endif
# cleaning .la files
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la

View File

@ -10,7 +10,6 @@
WANT_LDP ?= 1
WANT_PIM ?= 1
WANT_OSPFAPI ?= 1
WANT_TCP_ZEBRA ?= 0
WANT_BGP_VNC ?= 1
WANT_CUMULUS_MODE ?= 0
WANT_MULTIPATH ?= 1
@ -75,12 +74,6 @@ else
USE_OSPFAPI=--enable-ospfapi=no
endif
ifeq ($(WANT_TCP_ZEBRA),1)
USE_TCP_ZEBRA=--enable-tcp-zebra
else
USE_TCP_ZEBRA=--disable-tcp-zebra
endif
ifeq ($(WANT_BGP_VNC), 1)
USE_BGP_VNC=--enable-bgp-vnc=yes
else
@ -152,7 +145,6 @@ override_dh_auto_configure:
$(USE_OSPFAPI) \
$(USE_MULTIPATH) \
$(USE_LDP) \
$(USE_TCP_ZEBRA) \
--enable-fpm \
$(USE_FRR_USER) $(USE_FRR_GROUP) \
$(USE_FRR_VTY_GROUP) \
@ -194,12 +186,8 @@ override_dh_auto_install:
mkdir -p debian/tmp/etc/frr/
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
# installing the Frr specific SNMP MIB
ifeq ($(WANT_SNMP), 1)
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
else
# leftover from previously shipping SMUX client OID MIB
mkdir -p debian/tmp/usr/share/snmp/mibs/
endif
# cleaning .la files
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la

View File

@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \
developer/index.rst \
developer/ldpd-basic-test-setup.md \
developer/library.rst \
developer/logging.rst \
developer/Makefile.in \
developer/maintainer-release-build.rst \
developer/memtypes.rst \

View File

@ -7,6 +7,7 @@ Library Facilities (libfrr)
.. toctree::
:maxdepth: 2
logging
memtypes
hooks
cli

131
doc/developer/logging.rst Normal file
View File

@ -0,0 +1,131 @@
Developer's Guide to Logging
============================
One of the most frequent decisions to make while writing code for FRR is what
to log, what level to log it at, and when to log it. Here is a list of
recommendations for these decisions.
Errors and warnings
-------------------
If it is something that the user will want to look at and maybe do
something, it is either an **error** or a **warning**.
We're expecting that warnings and errors are in some way visible to the
user (in the worst case by looking at the log after the network broke, but
maybe by a syslog collector from all routers.) Therefore, anything that
needs to get the user in the loop—and only these things—are warnings or
errors.
Note that this doesn't neccessarily mean the user needs to fix something in
the FRR instance. It also includes when we detect something else needs
fixing, for example another router, the system we're running on, or the
configuration. The common point is that the user should probably do
*something*.
Deciding between a warning and an error is slightly less obvious; the rule
of thumb here is that an error will cause considerable fallout beyond its
direct effect. Closing a BGP session due to a malformed update is an error
since all routes from the peer are dropped; discarding one route because
its attributes don't make sense is a warning.
This also loosely corresponds to the kind of reaction we're expecting from
the user. An error is likely to need immediate response while a warning
might be snoozed for a bit and addressed as part of general maintenance.
If a problem will self-repair (e.g. by retransmits), it should be a
warning—unless the impact until that self-repair is very harsh.
Examples for warnings:
* a BGP update, LSA or LSP could not be processed, but operation is
proceeding and the broken pieces are likely to self-fix later
* some kind of controller cannot be reached, but we can work without it
* another router is using some unknown or unsupported capability
Examples for errors:
* dropping a BGP session due to malformed data
* a socket for routing protocol operation cannot be opened
* desynchronization from network state because something went wrong
* *everything that we as developers would really like to be notified about,
i.e. some assumption in the code isn't holding up*
Informational messages
----------------------
Anything that provides introspection to the user during normal operation
is an **info** message.
This includes all kinds of operational state transitions and events,
especially if they might be interesting to the user during the course of
figuring out a warning or an error.
By itself, these messages should mostly be statements of fact. They might
indicate the order and relationship in which things happened. Also covered
are conditions that might be "operational issues" like a link failure due
to an unplugged cable. If it's pretty much the point of running a routing
daemon for, it's not a warning or an error, just business as usual.
The user should be able to see the state of these bits from operational
state output, i.e. `show interface` or `show foobar neighbors`. The log
message indicating the change may have been printed weeks ago, but the
state can always be viewed. (If some state change has an info message but
no "show" command, maybe that command needs to be added.)
Examples:
* all kinds of up/down state changes
* interface coming up or going down
* addresses being added or deleted
* peers and neighbors coming up or going down
* rejection of some routes due to user-configured route maps
* backwards compatibility handling because another system on the network
has a different or smaller feature set
.. note::
The previously used **notify** priority is replaced with *info* in all
cases. We don't currently have a well-defined use case for it.
Debug messages and asserts
--------------------------
Everything that is only interesting on-demand, or only while developing,
is a **debug** message. It might be interesting to the user for a
particularly evasive issue, but in general these are details that an
average user might not even be able to make sense of.
Most (or all?) debug messages should be behind a `debug foobar` category
switch that controls which subset of these messages is currently
interesting and thus printed. If a debug message doesn't have such a
guard, there should be a good explanation as to why.
Conversely, debug messages are the only thing that should be guarded by
these switches. Neither info nor warning or error messages should be
hidden in this way.
**Asserts** should only be used as pretty crashes. We are expecting that
asserts remain enabled in production builds, but please try to not use
asserts in a way that would cause a security problem if the assert wasn't
there (i.e. don't use them for length checks.)
The purpose of asserts is mainly to help development and bug hunting. If
the daemon crashes, then having some more information is nice, and the
assert can provide crucial hints that cut down on the time needed to track
an issue. That said, if the issue can be reasonably handled and/or isn't
going to crash the daemon, it shouldn't be an assert.
For anything else where internal constraints are violated but we're not
breaking due to it, it's an error instead (not a debug.) These require
"user action" of notifying the developers.
Examples:
* mismatched :code:`prev`/:code:`next` pointers in lists
* some field that is absolutely needed is :code:`NULL`
* any other kind of data structure corruption that will cause the daemon
to crash sooner or later, one way or another

View File

@ -102,14 +102,6 @@ Zebra Protocol Commands
+-----------------------------------+-------+
| ZEBRA_INTERFACE_DOWN | 6 |
+-----------------------------------+-------+
| ZEBRA_IPV4_ROUTE_ADD | 7 |
+-----------------------------------+-------+
| ZEBRA_IPV4_ROUTE_DELETE | 8 |
+-----------------------------------+-------+
| ZEBRA_IPV6_ROUTE_ADD | 9 |
+-----------------------------------+-------+
| ZEBRA_IPV6_ROUTE_DELETE | 10 |
+-----------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ADD | 11 |
+-----------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DELETE | 12 |

View File

@ -126,7 +126,7 @@ These following options control the daemon's VTY (interactive command line) inte
staticd 2616
bfdd 2617
Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for the (insecure) TCP-ZEBRA interface.
Port 2607 is used for ospfd's Opaque LSA API.
.. option:: --vty_socket vty-path

View File

@ -6,6 +6,7 @@
.. toctree::
:maxdepth: 2
bfdd
bgpd
eigrpd
isisd

View File

@ -6,3 +6,50 @@ div.body {
pre {
background-color: #e2e2e2;
}
/* styling for the protocols vs. OS table in overview.rst */
/* first, general bits */
div.body td.mark {
text-align: center;
border-left: 1px solid #ccc;
}
table.mark th {
text-align: center;
}
table.mark td {
vertical-align: middle;
}
table.mark td[colspan="7"] {
text-align: center;
padding-top: 8pt;
padding-bottom: 2pt;
}
table.mark cite {
font-weight: bold;
}
/* individual Y/N/... cells */
td.mark {
width: 4.5em;
}
td.mark span {
display: block;
padding: 3px 1px;
border: 1px dotted #666;
width: 36pt;
margin:auto;
}
span.mark-y { background-color: #77ffaa; }
span.mark-geq { background-color: #aaff77; }
span.mark-cp { background-color: #ffbb55; }
span.mark-n { background-color: #ff8877; }
span.mark-dag { background-color: #ffee99; font-size: 8pt; padding:0px 1px; border-top:0px; }
/* for the legend below */
li span.mark {
display: inline-block;
padding: 3px 1px;
border: 1px dotted #666;
width: 36pt;
text-align: center;
}

View File

@ -0,0 +1,13 @@
/* special styling for the protocols vs. OS table in overview.rst
*
* unfortunately this can't be done in straight CSS because we're changing
* the styling on the parent.
*/
$(document).ready(function() {
$("span.mark:contains('Y')" ).addClass("mark-y" ).parent("td").addClass("mark");
$("span.mark:contains('≥')" ).addClass("mark-geq").parent("td").addClass("mark");
$("span.mark:contains('N')" ).addClass("mark-n" ).parent("td").addClass("mark");
$("span.mark:contains('CP')").addClass("mark-cp" ).parent("td").addClass("mark");
$("span.mark:contains('†')" ).addClass("mark-dag").parent("td").addClass("mark");
$('td.mark').parents('table').addClass("mark").children('colgroup').remove();
});

View File

@ -179,7 +179,7 @@ The following commands are available inside the BGP configuration node.
.. _bfd-ospf-peer-config:
OSPF BFD Configuration
---------------------
----------------------
The following commands are available inside the interface configuration node.
@ -364,7 +364,7 @@ You can inspect the current BFD peer status with the following commands:
Echo transmission interval: 50ms
frr# show bfd peer 192.168.0.1 json
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
You can also inspect peer session counters with the following commands:
@ -402,4 +402,4 @@ You can also inspect peer session counters with the following commands:
Zebra notifications: 4
frr# show bfd peer 192.168.0.1 counters json
{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}

View File

@ -1011,6 +1011,75 @@ is 4 octet long. The following format is used to define the community value.
``internet``
``internet`` represents well-known communities value 0.
``graceful-shutdown``
``graceful-shutdown`` represents well-known communities value
``GRACEFUL_SHUTDOWN`` ``0xFFFF0000`` ``65535:0``. :rfc:`8326` implements
the purpose Graceful BGP Session Shutdown to reduce the amount of
lost traffic when taking BGP sessions down for maintainance. The use
of the community needs to be supported from your peers side to
actually have any effect.
``accept-own``
``accept-own`` represents well-known communities value ``ACCEPT_OWN``
``0xFFFF0001`` ``65535:1``. :rfc:`7611` implements a way to signal
to a router to accept routes with a local nexthop address. This
can be the case when doing policing and having traffic having a
nexthop located in another VRF but still local interface to the
router. It is recommended to read the RFC for full details.
``route-filter-translated-v4``
``route-filter-translated-v4`` represents well-known communities value
``ROUTE_FILTER_TRANSLATED_v4`` ``0xFFFF0002`` ``65535:2``.
``route-filter-v4``
``route-filter-v4`` represents well-known communities value
``ROUTE_FILTER_v4`` ``0xFFFF0003`` ``65535:3``.
``route-filter-translated-v6``
``route-filter-translated-v6`` represents well-known communities value
``ROUTE_FILTER_TRANSLATED_v6`` ``0xFFFF0004`` ``65535:4``.
``route-filter-v6``
``route-filter-v6`` represents well-known communities value
``ROUTE_FILTER_v6`` ``0xFFFF0005`` ``65535:5``.
``llgr-stale``
``llgr-stale`` represents well-known communities value ``LLGR_STALE``
``0xFFFF0006`` ``65535:6``.
Assigned and intented only for use with routers supporting the
Long-lived Graceful Restart Capability as described in
:rfc:`draft-uttaro-idr-bgp-persistence`.
Routers recieving routes with this community may (depending on
implementation) choose allow to reject or modify routes on the
presence or absence of this community.
``no-llgr``
``no-llgr`` represents well-known communities value ``NO_LLGR``
``0xFFFF0007`` ``65535:7``.
Assigned and intented only for use with routers supporting the
Long-lived Graceful Restart Capability as described in
:rfc:`draft-uttaro-idr-bgp-persistence`.
Routers recieving routes with this community may (depending on
implementation) choose allow to reject or modify routes on the
presence or absence of this community.
``accept-own-nexthop``
``accept-own-nexthop`` represents well-known communities value
``accept-own-nexthop`` ``0xFFFF0008`` ``65535:8``.
:rfc:`draft-agrewal-idr-accept-own-nexthop` describes
how to tag and label VPN routes to be able to send traffic between VRFs
via an internal layer 2 domain on the same PE device. Refer to
:rfc:`draft-agrewal-idr-accept-own-nexthop` for full details.
``blackhole``
``blackhole`` represents well-known communities value ``BLACKHOLE``
``0xFFFF029A`` ``65535:666``. :rfc:`7999` documents sending prefixes to
EBGP peers and upstream for the purpose of blackholing traffic.
Prefixes tagged with the this community should normally not be
re-advertised from neighbors of the originating network. It is
recommended upon receiving prefixes tagged with this community to
add ``NO_EXPORT`` and ``NO_ADVERTISE``.
``no-export``
``no-export`` represents well-known communities value ``NO_EXPORT``
``0xFFFFFF01``. All routes carry this value must not be advertised to
@ -1030,6 +1099,11 @@ is 4 octet long. The following format is used to define the community value.
it is considered as external BGP peer, so the route will not be announced to
the peer.
``no-peer``
``no-peer`` represents well-known communities value ``NOPEER``
``0xFFFFFF04`` ``65535:65284``. :rfc:`3765` is used to communicate to
another network how the originating network want the prefix propagated.
When the communities attribute is received duplicate community values in the
attribute are ignored and value is sorted in numerical order.

View File

@ -358,6 +358,7 @@ def setup(app):
app.add_object_type('clicmd', 'clicmd')
# css overrides for HTML theme
app.add_stylesheet('overrides.css')
app.add_javascript('overrides.js')
# load Pygments lexer for FRR config syntax
#
# NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we

View File

@ -5,12 +5,12 @@ Overview
********
`FRR`_ is a routing software package that provides TCP/IP based routing
services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2,
OSPFv3, IS-IS, BGP-4, and BGP-4+ (:ref:`supported-rfcs`). FRR also supports
services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more
(see :ref:`supported-protocols`). FRR also supports
special BGP Route Reflector and Route Server behavior. In addition to
traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols.
With SNMP daemon which supports SMUX and AgentX protocol, FRR provides routing
protocol MIBs (:ref:`snmp-support`).
With an SNMP daemon that supports the AgentX protocol, FRR provides routing
protocol MIB read-only access (:ref:`snmp-support`).
FRR uses an advanced software architecture to provide you with a high quality,
multi server routing engine. FRR has an interactive user interface for each
@ -150,27 +150,93 @@ Recent versions of the following compilers are well tested:
.. _supported-protocols:
Supported Protocols & RFCs
==========================
Supported Protocols vs. Platform
================================
The following well-known protocols are supported:
The following table lists all protocols cross-refrenced to all operating
systems that have at least CI build tests. Note that for features, only
features with system dependencies are included here.
- BGP
- Babel
- EIGRP
- IS-IS
- LDP
- NHRP
- OSPFv2
- OSPFv3
- PIM
- RIP
- RIPNG
.. role:: mark
The following technologies are supported as well:
.. comment - the :mark:`X` pieces mesh with a little bit of JavaScript and
CSS in _static/overrides.{js,css} respectively. The JS code looks at the
presence of the 'Y' 'N' '≥' '†' or 'CP' strings. This seemed to be the
best / least intrusive way of getting a nice table in HTML. The table
will look somewhat shoddy on other sphinx targets like PDF or info (but
should still be readable.)
- PBR (Policy Based Routing)
- VNC (Virtual Network Control)
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| Daemon / Feature | Linux | OpenBSD | FreeBSD | NetBSD | Solaris |
+==+================================+================+==============+============+============+============+
| FRR Core |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `zebra` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| WAN / Carrier protocols |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `bgpd` (BGP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
| | | :mark:`†4.3` | | | | |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
| | | :mark:`†4.9` | | | | |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `ldpd` (LDP) | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| Link-State Routing |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `ospfd` (OSPFv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `ospf6d` (OSPFv3) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `isisd` (IS-IS) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| Distance-Vector Routing |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `ripd` (RIPv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `ripngd` (RIPng) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `babeld` (BABEL) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `eigrpd` (EIGRP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| Multicast Routing |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
| | ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
+--+--------------------------------+----------------+--------------+------------+------------+------------+
The indicators have the following semantics:
* :mark:`Y` - daemon/feature fully functional
* :mark:`≥X.X` - fully functional with kernel version X.X or newer
* :mark:`†X.X` - restricted functionality or impaired performance with kernel version X.X or newer
* :mark:`CP` - control plane only (i.e. BGP route server / route reflector)
* :mark:`N` - daemon/feature not supported by operating system
.. _supported-rfcs:

View File

@ -7,8 +7,8 @@ SNMP Support
:abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature
for collecting network information from router and/or host. FRR itself does
not support SNMP agent (server daemon) functionality but is able to connect to
a SNMP agent using the SMUX protocol (:rfc:`1227`) or the AgentX protocol
(:rfc:`2741`) and make the routing protocol MIBs available through it.
a SNMP agent using the the AgentX protocol (:rfc:`2741`) and make the
routing protocol MIBs available through it.
Note that SNMP Support needs to be enabled at compile-time and loaded as module
on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
@ -18,16 +18,10 @@ on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
Getting and installing an SNMP agent
====================================
There are several SNMP agent which support SMUX or AgentX. We recommend to use
The supported SNMP agent is AgentX. We recommend to use
the latest version of `net-snmp` which was formerly known as `ucd-snmp`. It is
free and open software and available at `http://www.net-snmp.org/ <http://www.net-snmp.org/>`_
and as binary package for most Linux distributions. `net-snmp` has to be
compiled with `--with-mib-modules=agentx` to be able to accept connections from
FRR using AgentX protocol or with `--with-mib-modules=smux` to use SMUX
protocol.
Nowadays, SMUX is a legacy protocol. The AgentX protocol should be preferred
for any new deployment. Both protocols have the same coverage.
and as binary package for most Linux distributions.
.. _agentx-configuration:
@ -42,7 +36,7 @@ master SNMP agent (snmpd) and each of the FRR daemons must be configured. In
:file:`/etc/snmp/snmpd.conf`, the ``master agentx`` directive should be added.
In each of the FRR daemons, ``agentx`` command will enable AgentX support.
:file:`/etc/snmp/snmpd.conf`:
:file:`/etc/snmp/zebra.conf`:
::
@ -97,105 +91,6 @@ need to configure FRR to use another transport, you can configure it through
agentXSocket tcp:192.168.15.12:705
.. _smux-configuration:
SMUX configuration
==================
To enable SMUX protocol support, FRR must have been build with the
:option:`--enable-snmp` option.
A separate connection has then to be established between the SNMP agent (snmpd)
and each of the FRR daemons. This connections each use different OID numbers
and passwords. Be aware that this OID number is not the one that is used in
queries by clients, it is solely used for the intercommunication of the
daemons.
In the following example the ospfd daemon will be connected to the snmpd daemon
using the password "frr_ospfd". For testing it is recommending to take exactly
the below snmpd.conf as wrong access restrictions can be hard to debug.
:file:`/etc/snmp/snmpd.conf`:
::
#
# example access restrictions setup
#
com2sec readonly default public
group MyROGroup v1 readonly
view all included .1 80
access MyROGroup "" any noauth exact all none none
#
# the following line is relevant for FRR
#
smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
:file:`/etc/frr/ospf`:
::
! ... the rest of ospfd.conf has been omitted for clarity ...
!
smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
!
After restarting snmpd and frr, a successful connection can be verified in the
syslog and by querying the SNMP daemon:
::
snmpd[12300]: [smux_accept] accepted fd 12 from 127.0.0.1:36255
snmpd[12300]: accepted smux peer: \\
oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, frr-0.96.5
# snmpwalk -c public -v1 localhost .1.3.6.1.2.1.14.1.1
OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109
Be warned that the current version (5.1.1) of the Net-SNMP daemon writes a line
for every SNMP connect to the syslog which can lead to enormous log file sizes.
If that is a problem you should consider to patch snmpd and comment out the
troublesome `snmp_log()` line in the function `netsnmp_agent_check_packet()` in
`agent/snmp_agent.c`.
MIB and command reference
=========================
The following OID numbers are used for the interprocess communication of snmpd and
the FRR daemons with SMUX only.::
. (OIDs below .iso.org.dod.internet.private.enterprises)
zebra .1.3.6.1.4.1.3317.1.2.1 .gnome.gnomeProducts.zebra.zserv
bgpd .1.3.6.1.4.1.3317.1.2.2 .gnome.gnomeProducts.zebra.bgpd
ripd .1.3.6.1.4.1.3317.1.2.3 .gnome.gnomeProducts.zebra.ripd
ospfd .1.3.6.1.4.1.3317.1.2.5 .gnome.gnomeProducts.zebra.ospfd
ospf6d .1.3.6.1.4.1.3317.1.2.6 .gnome.gnomeProducts.zebra.ospf6d
Sadly, SNMP has not been implemented in all daemons yet. The following
OID numbers are used for querying the SNMP daemon by a client:::
zebra .1.3.6.1.2.1.4.24 .iso.org.dot.internet.mgmt.mib-2.ip.ipForward
ospfd .1.3.6.1.2.1.14 .iso.org.dot.internet.mgmt.mib-2.ospf
bgpd .1.3.6.1.2.1.15 .iso.org.dot.internet.mgmt.mib-2.bgp
ripd .1.3.6.1.2.1.23 .iso.org.dot.internet.mgmt.mib-2.rip2
ospf6d .1.3.6.1.3.102 .iso.org.dod.internet.experimental.ospfv3
The following syntax is understood by the FRR daemons for configuring SNMP
using SMUX:
.. index:: smux peer OID
.. clicmd:: smux peer OID
.. index:: no smux peer OID
.. clicmd:: no smux peer OID
.. index:: smux peer OID PASSWORD
.. clicmd:: smux peer OID PASSWORD
.. index:: no smux peer OID PASSWORD
.. clicmd:: no smux peer OID PASSWORD
Here is the syntax for using AgentX:
.. index:: agentx

View File

@ -43,6 +43,7 @@
#include "isisd/isis_constants.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_network.h"
#include "isisd/isis_pdu.h"
#include "privs.h"

View File

@ -536,7 +536,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
*stream = stream_new(stream_size);
} else {
if (STREAM_SIZE(*stream) != stream_size)
stream_resize(*stream, stream_size);
stream_resize_inplace(stream, stream_size);
stream_reset(*stream);
}
}

View File

@ -274,19 +274,12 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
if (!b->head)
return BUFFER_EMPTY;
if (height < 1) {
zlog_warn(
"%s called with non-positive window height %d, forcing to 1",
__func__, height);
if (height < 1)
height = 1;
} else if (height >= 2)
else if (height >= 2)
height--;
if (width < 1) {
zlog_warn(
"%s called with non-positive window width %d, forcing to 1",
__func__, width);
if (width < 1)
width = 1;
}
/* For erase and more data add two to b's buffer_data count.*/
if (b->head->next == NULL) {
@ -334,11 +327,6 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
{
iov_alloc *= 2;
if (iov != small_iov) {
zlog_warn(
"%s: growing iov array to %d; "
"width %d, height %d, size %lu",
__func__, iov_alloc, width, height,
(unsigned long)b->size);
iov = XREALLOC(MTYPE_TMP, iov,
iov_alloc * sizeof(*iov));
} else {

View File

@ -24,6 +24,9 @@
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
# define _RET_NONNULL , returns_nonnull
#endif
#if __has_attribute(fallthrough)
# define _FALLTHROUGH __attribute__((fallthrough));
#endif
# define _CONSTRUCTOR(x) constructor(x)
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
@ -34,6 +37,9 @@
# define _DESTRUCTOR(x) destructor(x)
# define _ALLOC_SIZE(x) alloc_size(x)
#endif
#if __GNUC__ >= 7
# define _FALLTHROUGH __attribute__((fallthrough));
#endif
#endif
#ifdef __sun
@ -55,6 +61,9 @@
#ifndef _ALLOC_SIZE
# define _ALLOC_SIZE(x)
#endif
#ifndef _FALLTHROUGH
#define _FALLTHROUGH
#endif
/*
* for warnings on macros, put in the macro content like this:

View File

@ -107,7 +107,7 @@ struct log_ref *log_ref_get(uint32_t code)
void log_ref_display(struct vty *vty, uint32_t code, bool json)
{
struct log_ref *ref;
struct json_object *top, *obj;
struct json_object *top = NULL, *obj = NULL;
struct list *errlist;
struct listnode *ln;
@ -146,7 +146,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
char ubuf[256];
snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
code, ref->title);
ref->code, ref->title);
memset(ubuf, '=', strlen(pbuf));
ubuf[sizeof(ubuf) - 1] = '\0';

View File

@ -393,7 +393,8 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty)
* this should not be considered as an update
* then create the new interface
*/
if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id))
if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(
vrf_lookup_by_id(vrf_id)))
return if_create(name, vrf_id);
/* If it came from the kernel
* or by way of zclient, believe it and update
@ -471,6 +472,14 @@ int if_is_vrf(struct interface *ifp)
return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
}
bool if_is_loopback_or_vrf(struct interface *ifp)
{
if (if_is_loopback(ifp) || if_is_vrf(ifp))
return true;
return false;
}
/* Does this interface support broadcast ? */
int if_is_broadcast(struct interface *ifp)
{
@ -1140,7 +1149,7 @@ const char *if_link_type_str(enum zebra_link_type llt)
llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
default:
zlog_warn("Unknown value %d", llt);
flog_err(LIB_ERR_DEVELOPMENT, "Unknown value %d", llt);
return "Unknown type!";
#undef llts
}

View File

@ -497,6 +497,7 @@ extern int if_is_operative(struct interface *);
extern int if_is_no_ptm_operative(struct interface *);
extern int if_is_loopback(struct interface *);
extern int if_is_vrf(struct interface *ifp);
extern bool if_is_loopback_or_vrf(struct interface *ifp);
extern int if_is_broadcast(struct interface *);
extern int if_is_pointopoint(struct interface *);
extern int if_is_multicast(struct interface *);

View File

@ -868,11 +868,16 @@ int zlog_rotate(void)
save_errno = errno;
umask(oldumask);
if (zl->fp == NULL) {
pthread_mutex_unlock(&loglock);
flog_err_sys(
LIB_ERR_SYSTEM_CALL,
"Log rotate failed: cannot open file %s for append: %s",
zl->filename, safe_strerror(save_errno));
ret = -1;
pthread_mutex_lock(&loglock);
} else {
logfile_fd = fileno(zl->fp);
zl->maxlvl[ZLOG_DEST_FILE] = level;
@ -903,10 +908,6 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_ROUTE_ADD),
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
DESC_ENTRY(ZEBRA_IPV6_ROUTE_DELETE),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE),
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD),

View File

@ -87,7 +87,7 @@ extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
/* For logs which have error codes associated with them */
#define flog_err(ferr_id, format, ...) \
zlog_err("[EC %d] " format, ferr_id, ##__VA_ARGS__)
zlog_err("[EC %"PRIu32"] " format, ferr_id, ##__VA_ARGS__)
#define flog_err_sys(ferr_id, format, ...) \
flog_err(ferr_id, format, ##__VA_ARGS__)

1416
lib/smux.c

File diff suppressed because it is too large Load Diff

View File

@ -580,31 +580,7 @@ int sockopt_tcp_rtt(int sock)
int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
{
#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's
* version of the Quagga patch (based on work by Rick Payne, and Bruce
* Simpson)
*/
#define TCP_MD5_AUTH 13
#define TCP_MD5_AUTH_ADD 1
#define TCP_MD5_AUTH_DEL 2
struct tcp_rfc2385_cmd {
uint8_t command; /* Command - Add/Delete */
uint32_t address; /* IPV4 address associated */
uint8_t keylen; /* MD5 Key len (do NOT assume 0 terminated
ascii) */
void *key; /* MD5 Key */
} cmd;
struct in_addr *addr = &su->sin.sin_addr;
cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL);
cmd.address = addr->s_addr;
cmd.keylen = (password != NULL ? strlen(password) : 0);
cmd.key = password;
return setsockopt(sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
#elif HAVE_DECL_TCP_MD5SIG
#if HAVE_DECL_TCP_MD5SIG
int ret;
#ifndef GNU_LINUX
/*

View File

@ -143,7 +143,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread)
long spf_backoff_schedule(struct spf_backoff *backoff)
{
long rv;
long rv = 0;
struct timeval now;
gettimeofday(&now, NULL);
@ -176,9 +176,6 @@ long spf_backoff_schedule(struct spf_backoff *backoff)
else
rv = backoff->long_delay;
break;
default:
zlog_warn("SPF Back-off(%s) in unknown state", backoff->name);
rv = backoff->init_delay;
}
backoff_debug(

View File

@ -28,9 +28,9 @@
#include "network.h"
#include "prefix.h"
#include "log.h"
#include "lib_errors.h"
DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data")
DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
/* Tests whether a position is valid */
@ -100,9 +100,7 @@ struct stream *stream_new(size_t size)
assert(size > 0);
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream));
s->data = XMALLOC(MTYPE_STREAM_DATA, size);
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream) + size);
s->getp = s->endp = 0;
s->next = NULL;
@ -116,7 +114,6 @@ void stream_free(struct stream *s)
if (!s)
return;
XFREE(MTYPE_STREAM_DATA, s->data);
XFREE(MTYPE_STREAM, s);
}
@ -166,27 +163,33 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2,
return new;
}
size_t stream_resize(struct stream *s, size_t newsize)
size_t stream_resize_inplace(struct stream **sptr, size_t newsize)
{
uint8_t *newdata;
STREAM_VERIFY_SANE(s);
struct stream *orig = *sptr;
newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize);
STREAM_VERIFY_SANE(orig);
if (newdata == NULL)
return s->size;
orig = XREALLOC(MTYPE_STREAM, orig, sizeof(struct stream) + newsize);
s->data = newdata;
s->size = newsize;
orig->size = newsize;
if (s->endp > s->size)
s->endp = s->size;
if (s->getp > s->endp)
s->getp = s->endp;
if (orig->endp > orig->size)
orig->endp = orig->size;
if (orig->getp > orig->endp)
orig->getp = orig->endp;
STREAM_VERIFY_SANE(s);
STREAM_VERIFY_SANE(orig);
return s->size;
*sptr = orig;
return orig->size;
}
size_t __attribute__((deprecated))stream_resize_orig(struct stream *s,
size_t newsize)
{
assert("stream_resize: Switch code to use stream_resize_inplace" == NULL);
return stream_resize_inplace(&s, newsize);
}
size_t stream_get_getp(struct stream *s)

View File

@ -98,14 +98,15 @@
struct stream {
struct stream *next;
/* Remainder is ***private*** to stream
/*
* Remainder is ***private*** to stream
* direct access is frowned upon!
* Use the appropriate functions/macros
*/
size_t getp; /* next get position */
size_t endp; /* last valid data position */
size_t size; /* size of data segment */
unsigned char *data; /* data pointer */
size_t getp; /* next get position */
size_t endp; /* last valid data position */
size_t size; /* size of data segment */
unsigned char data[0]; /* data pointer */
};
/* First in first out queue structure. */
@ -154,7 +155,14 @@ extern struct stream *stream_new(size_t);
extern void stream_free(struct stream *);
extern struct stream *stream_copy(struct stream *, struct stream *src);
extern struct stream *stream_dup(struct stream *);
extern size_t stream_resize(struct stream *, size_t);
#if CONFDATE > 20190821
CPP_NOTICE("lib: time to remove stream_resize_orig")
#endif
extern size_t stream_resize_orig(struct stream *s, size_t newsize);
#define stream_resize stream_resize_orig
extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
extern size_t stream_get_getp(struct stream *);
extern size_t stream_get_endp(struct stream *);
extern size_t stream_get_size(struct stream *);

View File

@ -150,7 +150,6 @@ pkginclude_HEADERS += \
lib/sha256.h \
lib/sigevent.h \
lib/skiplist.h \
lib/smux.h \
lib/sockopt.h \
lib/sockunion.h \
lib/spf_backoff.h \
@ -199,7 +198,6 @@ lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
lib_libfrrsnmp_la_SOURCES = \
lib/agentx.c \
lib/smux.c \
lib/snmp.c \
# end

View File

@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node)
}
/* Unlock node. */
static inline struct route_node *route_unlock_node(struct route_node *node)
static inline void route_unlock_node(struct route_node *node)
{
assert(node->lock > 0);
(*(unsigned *)&node->lock)--;
if (node->lock == 0) {
if (node->lock == 0)
route_node_delete(node);
return NULL;
}
return node;
}
/*

View File

@ -36,6 +36,7 @@
DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master")
DEFINE_MTYPE_STATIC(LIB, THREAD_POLL, "Thread Poll Info")
DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
#if defined(__APPLE__)
@ -423,19 +424,11 @@ struct thread_master *thread_master_create(const char *name)
/* Initialize I/O task data structures */
getrlimit(RLIMIT_NOFILE, &limit);
rv->fd_limit = (int)limit.rlim_cur;
rv->read =
XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
if (rv->read == NULL) {
XFREE(MTYPE_THREAD_MASTER, rv);
return NULL;
}
rv->write =
XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
if (rv->write == NULL) {
XFREE(MTYPE_THREAD, rv->read);
XFREE(MTYPE_THREAD_MASTER, rv);
return NULL;
}
rv->read = XCALLOC(MTYPE_THREAD_POLL,
sizeof(struct thread *) * rv->fd_limit);
rv->write = XCALLOC(MTYPE_THREAD_POLL,
sizeof(struct thread *) * rv->fd_limit);
rv->cpu_record = hash_create_size(
8, (unsigned int (*)(void *))cpu_record_hash_key,
@ -539,17 +532,23 @@ static struct thread *thread_trim_head(struct thread_list *list)
return NULL;
}
#define THREAD_UNUSED_DEPTH 10
/* Move thread to unuse list. */
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
{
assert(m != NULL && thread != NULL);
assert(thread->next == NULL);
assert(thread->prev == NULL);
thread->ref = NULL;
thread->type = THREAD_UNUSED;
thread->hist->total_active--;
thread_list_add(&m->unuse, thread);
memset(thread, 0, sizeof(struct thread));
thread->type = THREAD_UNUSED;
if (m->unuse.count < THREAD_UNUSED_DEPTH)
thread_list_add(&m->unuse, thread);
else
XFREE(MTYPE_THREAD, thread);
}
/* Free all unused thread. */
@ -580,7 +579,7 @@ static void thread_array_free(struct thread_master *m,
m->alloc--;
}
}
XFREE(MTYPE_THREAD, thread_array);
XFREE(MTYPE_THREAD_POLL, thread_array);
}
static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
@ -1182,17 +1181,19 @@ void thread_cancel_event(struct thread_master *master, void *arg)
*/
void thread_cancel(struct thread *thread)
{
assert(thread->master->owner == pthread_self());
struct thread_master *master = thread->master;
pthread_mutex_lock(&thread->master->mtx);
assert(master->owner == pthread_self());
pthread_mutex_lock(&master->mtx);
{
struct cancel_req *cr =
XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
cr->thread = thread;
listnode_add(thread->master->cancel_req, cr);
do_thread_cancel(thread->master);
listnode_add(master->cancel_req, cr);
do_thread_cancel(master);
}
pthread_mutex_unlock(&thread->master->mtx);
pthread_mutex_unlock(&master->mtx);
}
/**

122
lib/vrf.c
View File

@ -342,91 +342,103 @@ void *vrf_info_lookup(vrf_id_t vrf_id)
}
/*
* VRF bit-map
* VRF hash for storing set or not.
*/
#define VRF_BITMAP_NUM_OF_GROUPS 1024
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
(VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT)
#define VRF_BITMAP_FLAG(_bit_offset) \
(((uint8_t)1) << ((_bit_offset) % CHAR_BIT))
struct vrf_bitmap {
uint8_t *groups[VRF_BITMAP_NUM_OF_GROUPS];
struct vrf_bit_set {
vrf_id_t vrf_id;
bool set;
};
static unsigned int vrf_hash_bitmap_key(void *data)
{
struct vrf_bit_set *bit = data;
return bit->vrf_id;
}
static int vrf_hash_bitmap_cmp(const void *a, const void *b)
{
const struct vrf_bit_set *bit1 = a;
const struct vrf_bit_set *bit2 = b;
return bit1->vrf_id == bit2->vrf_id;
}
static void *vrf_hash_bitmap_alloc(void *data)
{
struct vrf_bit_set *copy = data;
struct vrf_bit_set *bit;
bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
bit->vrf_id = copy->vrf_id;
return bit;
}
static void vrf_hash_bitmap_free(void *data)
{
struct vrf_bit_set *bit = data;
XFREE(MTYPE_VRF_BITMAP, bit);
}
vrf_bitmap_t vrf_bitmap_init(void)
{
return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
sizeof(struct vrf_bitmap));
return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
"VRF BIT HASH");
}
void vrf_bitmap_free(vrf_bitmap_t bmap)
{
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
int i;
struct hash *vrf_hash = bmap;
if (bmap == VRF_BITMAP_NULL)
if (vrf_hash == NULL)
return;
for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
if (bm->groups[i])
XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
XFREE(MTYPE_VRF_BITMAP, bm);
hash_clean(vrf_hash, vrf_hash_bitmap_free);
hash_free(vrf_hash);
}
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
{
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
struct hash *vrf_hash = bmap;
struct vrf_bit_set *bit;
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
return;
if (bm->groups[group] == NULL)
bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
VRF_BITMAP_FLAG(offset));
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
bit->set = true;
}
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
{
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
struct hash *vrf_hash = bmap;
struct vrf_bit_set *bit;
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|| bm->groups[group] == NULL)
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
return;
UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
VRF_BITMAP_FLAG(offset));
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
bit->set = false;
}
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
{
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
struct hash *vrf_hash = bmap;
struct vrf_bit_set *bit;
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|| bm->groups[group] == NULL)
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
return 0;
return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
VRF_BITMAP_FLAG(offset))
? 1
: 0;
bit = hash_lookup(vrf_hash, &lookup);
if (bit)
return bit->set;
return 0;
}
static void vrf_autocomplete(vector comps, struct cmd_token *token)
@ -682,10 +694,8 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
return CMD_SUCCESS;
}
int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
int vrf_is_mapped_on_netns(struct vrf *vrf)
{
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
if (!vrf || vrf->data.l.netns_name[0] == '\0')
return 0;
if (vrf->vrf_id == VRF_DEFAULT)
@ -887,7 +897,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
if (fd < 0 || name == NULL)
return fd;
if (vrf_is_mapped_on_netns(vrf_id))
if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id)))
return fd;
#ifdef SO_BINDTODEVICE
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);

View File

@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void);
#define VRF_DEFAULT vrf_get_default_id()
/* VRF is mapped on netns or not ? */
int vrf_is_mapped_on_netns(vrf_id_t vrf_id);
int vrf_is_mapped_on_netns(struct vrf *vrf);
/* VRF switch from NETNS */
extern int vrf_switch_to_netns(vrf_id_t vrf_id);

View File

@ -676,11 +676,11 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
* "xdr_encode"-like interface that allows daemon (client) to send
* a message to zebra server for a route that needs to be
* added/deleted to the kernel. Info about the route is specified
* by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
* by the caller in a struct zapi_route. zapi_route_encode() then writes
* the info down the zclient socket using the stream_* functions.
*
* The corresponding read ("xdr_decode") function on the server
* side is zread_ipv4_add()/zread_ipv4_delete().
* side is zapi_route_decode().
*
* 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -707,21 +707,16 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
* is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole
* nexthop.
*
* The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
* infrastructure was built around the traditional (32-bit "gate OR
* ifindex") nexthop data unit. A special encoding can be used to feed
* onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
* using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
* fields as follows:
* The original struct zapi_route_*() infrastructure was built around
* the traditional (32-bit "gate OR ifindex") nexthop data unit.
* A special encoding can be used to feed onlink (64-bit "gate AND ifindex")
* nexthops into zapi_route_encode() using the same zapi_route structure.
* This is done by setting zapi_route fields as follows:
* - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
* - .nexthop_num == .ifindex_num
* - .nexthop and .ifindex are filled with gate and ifindex parts of
* each compound nexthop, both in the same order
*
* zapi_ipv4_route() will produce two nexthop data units for each such
* interleaved 64-bit nexthop. On the zserv side of the socket it will be
* mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure.
*
* If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
* byte value.
*
@ -734,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
*
* XXX: No attention paid to alignment.
*/
int zapi_ipv4_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv4 *p,
struct zapi_ipv4 *api)
{
int i;
int psize;
struct stream *s;
/* Reset stream. */
s = zclient->obuf;
stream_reset(s);
/* Some checks for labeled-unicast. The current expectation is that each
* nexthop is accompanied by a label in the case of labeled-unicast.
*/
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
/* We expect prefixes installed with labels and the number to
* match
* the number of nexthops.
*/
assert(api->label_num == api->nexthop_num);
}
zclient_create_header(s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc(s, api->type);
stream_putw(s, api->instance);
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putw(s, api->safi);
/* Put prefix information. */
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (uint8_t *)&p->prefix, psize);
/* Nexthop, ifindex, distance and metric information. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
stream_putc(s, api->nexthop_num + api->ifindex_num);
for (i = 0; i < api->nexthop_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr(s, api->nexthop[i]);
/* For labeled-unicast, each nexthop is followed by
* label. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
stream_putl(s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
stream_putl(s, api->ifindex[i]);
}
}
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
stream_putl(s, api->metric);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
stream_putl(s, api->tag);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
stream_putl(s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
int zapi_ipv4_route_ipv6_nexthop(uint8_t cmd, struct zclient *zclient,
struct prefix_ipv4 *p, struct zapi_ipv6 *api)
{
int i;
int psize;
struct stream *s;
/* Reset stream. */
s = zclient->obuf;
stream_reset(s);
/* Some checks for labeled-unicast. The current expectation is that each
* nexthop is accompanied by a label in the case of labeled-unicast.
*/
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
/* We expect prefixes installed with labels and the number to
* match
* the number of nexthops.
*/
assert(api->label_num == api->nexthop_num);
}
zclient_create_header(s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc(s, api->type);
stream_putw(s, api->instance);
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putw(s, api->safi);
/* Put prefix information. */
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (uint8_t *)&p->prefix, psize);
/* Nexthop, ifindex, distance and metric information. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
stream_putc(s, api->nexthop_num + api->ifindex_num);
for (i = 0; i < api->nexthop_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IPV6);
stream_write(s, (uint8_t *)api->nexthop[i], 16);
/* For labeled-unicast, each nexthop is followed by
* label. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
stream_putl(s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
stream_putl(s, api->ifindex[i]);
}
}
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
stream_putl(s, api->metric);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
stream_putl(s, api->tag);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
stream_putl(s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv6 *p,
struct prefix_ipv6 *src_p, struct zapi_ipv6 *api)
{
int i;
int psize;
struct stream *s;
/* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL
*/
assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p);
/* Reset stream. */
s = zclient->obuf;
stream_reset(s);
/* Some checks for labeled-unicast. The current expectation is that each
* nexthop is accompanied by a label in the case of labeled-unicast.
*/
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
/* We expect prefixes installed with labels and the number to
* match
* the number of nexthops.
*/
assert(api->label_num == api->nexthop_num);
}
zclient_create_header(s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc(s, api->type);
stream_putw(s, api->instance);
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putw(s, api->safi);
/* Put prefix information. */
psize = PSIZE(p->prefixlen);
stream_putc(s, p->prefixlen);
stream_write(s, (uint8_t *)&p->prefix, psize);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
psize = PSIZE(src_p->prefixlen);
stream_putc(s, src_p->prefixlen);
stream_write(s, (uint8_t *)&src_p->prefix, psize);
}
/* Nexthop, ifindex, distance and metric information. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
stream_putc(s, api->nexthop_num + api->ifindex_num);
for (i = 0; i < api->nexthop_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IPV6);
stream_write(s, (uint8_t *)api->nexthop[i], 16);
/* For labeled-unicast, each nexthop is followed by
* label. */
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
stream_putl(s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++) {
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
stream_putl(s, api->ifindex[i]);
}
}
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
stream_putc(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
stream_putl(s, api->metric);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
stream_putl(s, api->tag);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
stream_putl(s, api->mtu);
/* Put length at the first point of the stream. */
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
int zclient_route_send(uint8_t cmd, struct zclient *zclient,
struct zapi_route *api)
{

View File

@ -73,10 +73,6 @@ typedef enum {
ZEBRA_ROUTE_ADD,
ZEBRA_ROUTE_DELETE,
ZEBRA_ROUTE_NOTIFY_OWNER,
ZEBRA_IPV4_ROUTE_ADD,
ZEBRA_IPV4_ROUTE_DELETE,
ZEBRA_IPV6_ROUTE_ADD,
ZEBRA_IPV6_ROUTE_DELETE,
ZEBRA_REDISTRIBUTE_ADD,
ZEBRA_REDISTRIBUTE_DELETE,
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
@ -286,7 +282,7 @@ struct zclient {
*/
#define ZAPI_MESSAGE_TABLEID 0x80
#define ZSERV_VERSION 5
#define ZSERV_VERSION 6
/* Zserv protocol message header */
struct zmsghdr {
uint16_t length;
@ -353,37 +349,6 @@ struct zapi_route {
uint32_t tableid;
};
/* Zebra IPv4 route message API. */
struct zapi_ipv4 {
uint8_t type;
unsigned short instance;
uint32_t flags;
uint8_t message;
safi_t safi;
uint8_t nexthop_num;
struct in_addr **nexthop;
uint8_t ifindex_num;
ifindex_t *ifindex;
uint8_t label_num;
unsigned int *label;
uint8_t distance;
uint32_t metric;
route_tag_t tag;
uint32_t mtu;
vrf_id_t vrf_id;
};
struct zapi_pw {
char ifname[IF_NAMESIZE];
ifindex_t ifindex;
@ -600,15 +565,6 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
/* clang-format off */
#if CONFDATE > 20180823
CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
#endif
/* clang-format on */
extern int zapi_ipv4_route(uint8_t, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated));
extern struct interface *zebra_interface_link_params_read(struct stream *);
extern size_t zebra_interface_link_params_write(struct stream *,
struct interface *);
@ -635,45 +591,6 @@ extern void zebra_read_pw_status_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id,
struct zapi_pw_status *pw);
/* IPv6 prefix add and delete function prototype. */
struct zapi_ipv6 {
uint8_t type;
unsigned short instance;
uint32_t flags;
uint8_t message;
safi_t safi;
uint8_t nexthop_num;
struct in6_addr **nexthop;
uint8_t ifindex_num;
ifindex_t *ifindex;
uint8_t label_num;
unsigned int *label;
uint8_t distance;
uint32_t metric;
route_tag_t tag;
uint32_t mtu;
vrf_id_t vrf_id;
};
extern int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient,
struct prefix_ipv6 *p, struct prefix_ipv6 *src_p,
struct zapi_ipv6 *api) __attribute__((deprecated));
extern int zapi_ipv4_route_ipv6_nexthop(uint8_t, struct zclient *,
struct prefix_ipv4 *,
struct zapi_ipv6 *)
__attribute__((deprecated));
extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *);
extern int zclient_send_rnh(struct zclient *zclient, int command,
struct prefix *p, bool exact_match,

View File

@ -46,6 +46,7 @@
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_api.h"

View File

@ -1425,19 +1425,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
newlsa->length = htons(length);
/* Create OSPF LSA. */
if ((new = ospf_lsa_new()) == NULL) {
zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
stream_free(s);
return NULL;
}
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
zlog_warn(
"ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
ospf_lsa_unlock(&new);
stream_free(s);
return NULL;
}
new = ospf_lsa_new_and_data(length);
new->area = area;
new->oi = oi;

View File

@ -73,26 +73,6 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
p->prefixlen);
}
/* Lookup external route. */
struct ospf_route *ospf_external_route_lookup(struct ospf *ospf,
struct prefix_ipv4 *p)
{
struct route_node *rn;
rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p);
if (rn) {
route_unlock_node(rn);
if (rn->info)
return rn->info;
}
zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p->prefix),
p->prefixlen);
return NULL;
}
/* Add an External info for AS-external-LSA. */
struct external_info *ospf_external_info_new(uint8_t type,
unsigned short instance)

View File

@ -68,8 +68,6 @@ extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
unsigned short,
struct prefix_ipv4 *);
extern struct ospf_route *ospf_external_route_lookup(struct ospf *,
struct prefix_ipv4 *);
extern void ospf_asbr_status_update(struct ospf *, uint8_t);
extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);

View File

@ -288,6 +288,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
struct prefix_ipv4 asbr, p;
struct route_node *rn;
struct ospf_route *new, * or ;
char buf1[INET_ADDRSTRLEN];
int ret;
assert(lsa);
@ -304,10 +305,14 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
return 0;
}
if (IS_DEBUG_OSPF(lsa, LSA))
if (IS_DEBUG_OSPF(lsa, LSA)) {
snprintf(buf1, INET_ADDRSTRLEN, "%s",
inet_ntoa(al->header.adv_router));
zlog_debug(
"Route[External]: Calculate AS-external-LSA to %s/%d",
inet_ntoa(al->header.id), ip_masklen(al->mask));
"Route[External]: Calculate AS-external-LSA to %s/%d adv_router %s",
inet_ntoa(al->header.id), ip_masklen(al->mask), buf1);
}
/* (1) If the cost specified by the LSA is LSInfinity, or if the
LSA's LS age is equal to MaxAge, then examine the next LSA. */
if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) {
@ -459,8 +464,9 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
if (!rn || (or = rn->info) == NULL) {
if (IS_DEBUG_OSPF(lsa, LSA))
zlog_debug("Route[External]: Adding a new route %s/%d",
inet_ntoa(p.prefix), p.prefixlen);
zlog_debug("Route[External]: Adding a new route %s/%d with paths %u",
inet_ntoa(p.prefix), p.prefixlen,
listcount(asbr_route->paths));
ospf_route_add(ospf->new_external_route, &p, new, asbr_route);

View File

@ -977,20 +977,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area,
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new();
if (new == NULL) {
zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
stream_free(s);
return NULL;
}
new->data = ospf_lsa_data_new(length);
if (new->data == NULL) {
zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return NULL;
}
new = ospf_lsa_new_and_data(length);
/* Segment Routing belongs only to default VRF */
new->vrf_id = VRF_DEFAULT;
@ -1056,20 +1043,7 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area,
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
new = ospf_lsa_new();
if (new == NULL) {
zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
stream_free(s);
return NULL;
}
new->data = ospf_lsa_data_new(length);
if (new->data == NULL) {
zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return NULL;
}
new = ospf_lsa_new_and_data(length);
/* Segment Routing belongs only to default VRF */
new->vrf_id = VRF_DEFAULT;

View File

@ -810,8 +810,7 @@ struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah)
{
struct ospf_lsa *new;
new = ospf_lsa_new();
new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE);
new = ospf_lsa_new_and_data(OSPF_LSA_HEADER_SIZE);
memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE);
return new;

View File

@ -167,6 +167,16 @@ struct ospf_lsa *ospf_lsa_new()
return new;
}
struct ospf_lsa *ospf_lsa_new_and_data(size_t size)
{
struct ospf_lsa *new;
new = ospf_lsa_new();
new->data = ospf_lsa_data_new(size);
return new;
}
/* Duplicate OSPF LSA. */
struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa)
{
@ -406,7 +416,7 @@ static uint16_t ospf_link_cost(struct ospf_interface *oi)
}
/* Set a link information. */
static char link_info_set(struct stream *s, struct in_addr id,
static char link_info_set(struct stream **s, struct in_addr id,
struct in_addr data, uint8_t type, uint8_t tos,
uint16_t cost)
{
@ -415,11 +425,11 @@ static char link_info_set(struct stream *s, struct in_addr id,
* more.
* we try accomodate those here.
*/
if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) {
if (STREAM_WRITEABLE(*s) < OSPF_ROUTER_LSA_LINK_SIZE) {
size_t ret = OSPF_MAX_LSA_SIZE;
/* Can we enlarge the stream still? */
if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) {
if (STREAM_SIZE(*s) == OSPF_MAX_LSA_SIZE) {
/* we futz the size here for simplicity, really we need
* to account
* for just:
@ -431,30 +441,31 @@ static char link_info_set(struct stream *s, struct in_addr id,
*
* Simpler just to subtract OSPF_MAX_LSA_SIZE though.
*/
ret = stream_resize(
ret = stream_resize_inplace(
s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
}
if (ret == OSPF_MAX_LSA_SIZE) {
zlog_warn(
"%s: Out of space in LSA stream, left %zd, size %zd",
__func__, STREAM_WRITEABLE(s), STREAM_SIZE(s));
__func__, STREAM_WRITEABLE(*s),
STREAM_SIZE(*s));
return 0;
}
}
/* TOS based routing is not supported. */
stream_put_ipv4(s, id.s_addr); /* Link ID. */
stream_put_ipv4(s, data.s_addr); /* Link Data. */
stream_putc(s, type); /* Link Type. */
stream_putc(s, tos); /* TOS = 0. */
stream_putw(s, cost); /* Link Cost. */
stream_put_ipv4(*s, id.s_addr); /* Link ID. */
stream_put_ipv4(*s, data.s_addr); /* Link Data. */
stream_putc(*s, type); /* Link Type. */
stream_putc(*s, tos); /* TOS = 0. */
stream_putw(*s, cost); /* Link Cost. */
return 1;
}
/* Describe Point-to-Point link (Section 12.4.1.1). */
static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
{
int links = 0;
struct ospf_neighbor *nbr;
@ -500,7 +511,7 @@ static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
}
/* Describe Broadcast Link. */
static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
{
struct ospf_neighbor *dr;
struct in_addr id, mask;
@ -546,7 +557,7 @@ static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
}
}
static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi)
{
struct in_addr id, mask;
@ -560,7 +571,8 @@ static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
}
/* Describe Virtual Link. */
static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
static int lsa_link_virtuallink_set(struct stream **s,
struct ospf_interface *oi)
{
struct ospf_neighbor *nbr;
uint16_t cost = ospf_link_cost(oi);
@ -583,7 +595,7 @@ static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
12.4.1.4.*/
/* from "edward rrr" <edward_rrr@hotmail.com>
http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi)
{
int links = 0;
struct route_node *rn;
@ -624,7 +636,7 @@ static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
}
/* Set router-LSA link information. */
static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
static int router_lsa_link_set(struct stream **s, struct ospf_area *area)
{
struct listnode *node;
struct ospf_interface *oi;
@ -667,28 +679,28 @@ static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
}
/* Set router-LSA body. */
static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area)
static void ospf_router_lsa_body_set(struct stream **s, struct ospf_area *area)
{
unsigned long putp;
uint16_t cnt;
/* Set flags. */
stream_putc(s, router_lsa_flags(area));
stream_putc(*s, router_lsa_flags(area));
/* Set Zero fields. */
stream_putc(s, 0);
stream_putc(*s, 0);
/* Keep pointer to # links. */
putp = stream_get_endp(s);
putp = stream_get_endp(*s);
/* Forward word */
stream_putw(s, 0);
stream_putw(*s, 0);
/* Set all link information. */
cnt = router_lsa_link_set(s, area);
/* Set # of links here. */
stream_putw_at(s, putp, cnt);
stream_putw_at(*s, putp, cnt);
}
static int ospf_stub_router_timer(struct thread *t)
@ -773,7 +785,7 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
/* Set router-LSA body fields. */
ospf_router_lsa_body_set(s, area);
ospf_router_lsa_body_set(&s, area);
/* Set length. */
length = stream_get_endp(s);
@ -781,17 +793,13 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
lsah->length = htons(length);
/* Now, create OSPF LSA instance. */
if ((new = ospf_lsa_new()) == NULL) {
zlog_err("%s: Unable to create new lsa", __func__);
return NULL;
}
new = ospf_lsa_new_and_data(length);
new->area = area;
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
new->vrf_id = area->ospf->vrf_id;
/* Copy LSA data to store, discard stream. */
new->data = ospf_lsa_data_new(length);
memcpy(new->data, lsah, length);
stream_free(s);
@ -997,17 +1005,13 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi)
lsah->length = htons(length);
/* Create OSPF LSA instance. */
if ((new = ospf_lsa_new()) == NULL) {
zlog_err("%s: ospf_lsa_new returned NULL", __func__);
return NULL;
}
new = ospf_lsa_new_and_data(length);
new->area = oi->area;
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
new->vrf_id = oi->ospf->vrf_id;
/* Copy LSA to store. */
new->data = ospf_lsa_data_new(length);
memcpy(new->data, lsah, length);
stream_free(s);
@ -1181,13 +1185,12 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area,
lsah->length = htons(length);
/* Create OSPF LSA instance. */
new = ospf_lsa_new();
new = ospf_lsa_new_and_data(length);
new->area = area;
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
new->vrf_id = area->ospf->vrf_id;
/* Copy LSA to store. */
new->data = ospf_lsa_data_new(length);
memcpy(new->data, lsah, length);
stream_free(s);
@ -1323,13 +1326,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area,
lsah->length = htons(length);
/* Create OSPF LSA instance. */
new = ospf_lsa_new();
new = ospf_lsa_new_and_data(length);
new->area = area;
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
new->vrf_id = area->ospf->vrf_id;
/* Copy LSA to store. */
new->data = ospf_lsa_data_new(length);
memcpy(new->data, lsah, length);
stream_free(s);
@ -1629,14 +1631,13 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
lsah->length = htons(length);
/* Now, create OSPF LSA instance. */
new = ospf_lsa_new();
new = ospf_lsa_new_and_data(length);
new->area = NULL;
SET_FLAG(new->flags,
OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
new->vrf_id = ospf->vrf_id;
/* Copy LSA data to store, discard stream. */
new->data = ospf_lsa_data_new(length);
memcpy(new->data, lsah, length);
stream_free(s);

View File

@ -235,6 +235,7 @@ extern int ospf_check_nbr_status(struct ospf *);
/* Prototype for LSA primitive. */
extern struct ospf_lsa *ospf_lsa_new(void);
extern struct ospf_lsa *ospf_lsa_new_and_data(size_t size);
extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *);
extern void ospf_lsa_free(struct ospf_lsa *);
extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);

View File

@ -49,6 +49,7 @@
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_vty.h"
#include "ospfd/ospf_bfd.h"

View File

@ -1742,7 +1742,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
}
/* Create OSPF LSA instance. */
lsa = ospf_lsa_new();
lsa = ospf_lsa_new_and_data(length);
lsa->vrf_id = oi->ospf->vrf_id;
/* We may wish to put some error checking if type NSSA comes in
@ -1761,7 +1761,6 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
break;
}
lsa->data = ospf_lsa_data_new(length);
memcpy(lsa->data, lsah, length);
if (IS_DEBUG_OSPF_EVENT)

View File

@ -775,18 +775,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
if ((new = ospf_lsa_new()) == NULL) {
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
stream_free(s);
return NULL;
}
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return new;
}
new = ospf_lsa_new_and_data(length);
new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
scope, fulfill otherwise */

View File

@ -47,6 +47,7 @@
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
/* OSPF2-MIB. */

View File

@ -1201,18 +1201,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
if ((new = ospf_lsa_new()) == NULL) {
zlog_warn("%s: ospf_lsa_new() ?", __func__);
stream_free(s);
return NULL;
}
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
zlog_warn("%s: ospf_lsa_data_new() ?", __func__);
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return new;
}
new = ospf_lsa_new_and_data(length);
new->vrf_id = ospf->vrf_id;
if (area && area->ospf)

View File

@ -111,10 +111,11 @@ static int ospf_interface_add(int command, struct zclient *zclient,
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d",
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u",
ifp->name, ospf_vrf_id_to_name(ifp->vrf_id),
ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu,
ifp->speed);
assert(ifp->info);
@ -128,6 +129,8 @@ static int ospf_interface_add(int command, struct zclient *zclient,
if (!ospf)
return 0;
ospf_if_recalculate_output_cost(ifp);
ospf_if_update(ospf, ifp);
hook_call(ospf_if_update, ifp);
@ -448,14 +451,17 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
count++;
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
char buf[2][PREFIX2STR_BUFFER];
char buf[2][INET_ADDRSTRLEN];
struct interface *ifp;
ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id);
zlog_debug(
"Zebra: Route add %s nexthop %s, ifindex=%d",
"Zebra: Route add %s nexthop %s, ifindex=%d %s",
prefix2str(p, buf[0], sizeof(buf[0])),
inet_ntop(AF_INET, &path->nexthop,
buf[1], sizeof(buf[1])),
path->ifindex);
path->ifindex, ifp ? ifp->name : " ");
}
}
api.nexthop_num = count;

View File

@ -52,10 +52,10 @@
#include "ospfd/ospf_spf.h"
#include "ospfd/ospf_packet.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_ase.h"

View File

@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
char addr_str[INET_ADDRSTRLEN];
struct pim_assert_metric *am;
struct in_addr ifaddr;
char pref_str[5];
char metr_str[7];
char pref_str[16];
char metr_str[16];
ifaddr = pim_ifp->primary_address;

View File

@ -1495,14 +1495,6 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
return 0;
}
bool pim_if_is_loopback(struct interface *ifp)
{
if (if_is_loopback(ifp) || if_is_vrf(ifp))
return true;
return false;
}
bool pim_if_is_vrf_device(struct interface *ifp)
{
if (if_is_vrf(ifp))

View File

@ -207,8 +207,6 @@ void pim_if_create_pimreg(struct pim_instance *pim);
int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
int pim_update_source_set(struct interface *ifp, struct in_addr source);
bool pim_if_is_loopback(struct interface *ifp);
bool pim_if_is_vrf_device(struct interface *ifp);
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);

View File

@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
ifchannel list is empty before deleting upstream_del
ref count will take care of it.
*/
pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
if (ch->upstream->ref_count > 0)
pim_upstream_del(pim_ifp->pim, ch->upstream,
__PRETTY_FUNCTION__);
else
zlog_warn("%s: Avoiding deletion of upstream with ref_count %d "
"from ifchannel(%s): %s", __PRETTY_FUNCTION__,
ch->upstream->ref_count, ch->interface->name,
ch->sg_str);
ch->upstream = NULL;
THREAD_OFF(ch->t_ifjoin_expiry_timer);

View File

@ -37,19 +37,20 @@
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
{
char *out;
struct prefix_sg sg;
int i;
sg.src = c_oil->oil.mfcc_origin;
sg.grp = c_oil->oil.mfcc_mcastgrp;
sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
c_oil->oil.mfcc_parent);
snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
c_oil->oil.mfcc_parent);
out = buf + strlen(buf);
for (i = 0; i < MAXVIFS; i++) {
if (c_oil->oil.mfcc_ttls[i] != 0) {
char buf1[10];
sprintf(buf1, "%d ", i);
strcat(buf, buf1);
snprintf(out, buf + size - out, "%d ", i);
out += strlen(out);
}
}

View File

@ -655,7 +655,7 @@ static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
{
struct pim_interface *pim_ifp = ifp->info;
if (pim_if_is_loopback(ifp))
if (if_is_loopback_or_vrf(ifp))
return 0;
if (hello_send(ifp, holdtime)) {
@ -757,7 +757,7 @@ void pim_hello_restart_triggered(struct interface *ifp)
/*
* No need to ever start loopback or vrf device hello's
*/
if (pim_if_is_loopback(ifp))
if (if_is_loopback_or_vrf(ifp))
return;
/*

View File

@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
up->ref_count, up->flags,
up->channel_oil->oil_ref_count);
assert(up->ref_count > 0);
--up->ref_count;
if (up->ref_count >= 1)

View File

@ -31,7 +31,7 @@ Commands defined by this snap
- `frr.readme`:
Returns this document `cat README_usage.md`
- `frr.set`:
Allows to enable `FPM` module. See FPM section below
Allows to enable `FPM` and/or disable RPKIi module. See Module section below
and for debugging defined at this time (May get removed later - do not
depend on them). These are mainly intended to debug the Snap
@ -100,13 +100,13 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in
These settings require either a reboot or a manual configuration with
`sysctl` as well.
FPM Module
Modules
----------
The `frr.set` allows to turn FPM module on or off.
The `frr.set` allows to turn FPM module ond the RPKI module on or off.
frr.set fpm {disable|protobuf|netlink}
Disables FPM or enables FPM with selected mode
Disables FPM or enables FPM with selected mode (default: disabled)
By default, the FPM module is disabled, but installed with netlink and
protobuf support. To enable the FPM module, use the `frr.set fpm protobuf`
@ -114,6 +114,17 @@ or `frr.set fpm netlink` command. The command will only enable the mode
for the next restart of zebra. Please reboot or restart zebra after
changing the mode to become effective.
frr.set rpki {enable|disable}
Disables or enables BGP RPKI (default: enabled)
By default, the RPKI module is enabled. To disable the RPKI module
use the `frr.set rpki disable` command. The command will only enable
the module after the next restart of the bgp daemon. Please reboot or
restart bgpd after changing the mode to become effective.
(Normally, there is no need to disable the module as it has no effect
if there are no RPKI configurations in BGP)
FAQ
---
- frr.vtysh displays `--MORE--` on long output. How to suppress this?

View File

@ -5,9 +5,16 @@ set -e -x
if ! [ -e $SNAP_DATA/bgpd.conf ]; then
cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
fi
# If no RPKI option is specified, then we create a default
# with RPKI enabled
if ! [ -e $SNAP_DATA/rpki.conf ]; then
echo "-M rpki" > $SNAP_DATA/rpki.conf
fi
EXTRA_OPTIONS="`cat $SNAP_DATA/rpki.conf`"
exec $SNAP/sbin/bgpd \
-f $SNAP_DATA/bgpd.conf \
--pid_file $SNAP_DATA/bgpd.pid \
--socket $SNAP_DATA/zsock \
--vty_socket $SNAP_DATA
--vty_socket $SNAP_DATA \
--moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS

View File

@ -28,11 +28,34 @@ case $1 in
;;
esac
;;
rpki)
case $2 in
disable)
echo "" > $SNAP_DATA/rpki.conf
echo "RPKI module disabled. Please restart FRR"
;;
enable)
echo "-M rpki" > $SNAP_DATA/rpki.conf
echo "RPKI module enabled. Please restart FRR"
;;
*)
echo "Usage:"
echo " ${SNAP_NAME}.set rpki {disable|enable}"
echo ""
echo " Disables BGP RPKI module or enables it (default: enabled)"
echo " Mode will be saved for next restart of bgpd, but bgpd"
echo " is not automatically restarted"
exit 1
;;
esac
;;
*)
echo "Usage:"
echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
echo " ${SNAP_NAME}.set rpki {disable|enable}"
echo ""
echo " Disables FPM or enables FPM with selected mode"
echo " fpm: Disables FPM or enables FPM with selected mode"
echo " rpki: Disables BGP RPKI or enables it (default: enabled)"
exit 1
;;
esac

View File

@ -136,7 +136,7 @@ apps:
- network-bind
- network-control
bgpd-debug:
command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA --moduledir $SNAP/lib/frr/modules `cat $SNAP_DATA/rpki.conf 2> /dev/null`
plugs:
- network
- network-bind
@ -221,8 +221,27 @@ apps:
- network-control
parts:
rtrlib:
build-packages:
- cmake
- make
- gcc
- libssh-dev
stage-packages:
- libssh-4
prime:
- lib/x86_64-linux-gnu/librtr.so*
- usr/lib/x86_64-linux-gnu/libssh.so*
source: https://github.com/rtrlib/rtrlib.git
source-type: git
source-tag: v0.5.0
plugin: cmake
configflags:
- -DCMAKE_BUILD_TYPE=Release
frr:
build-packages:
after: [rtrlib]
build-packages:
- gcc
- autoconf
- automake
- libtool
@ -247,6 +266,7 @@ parts:
- flex
- python3-dev
- protobuf-c-compiler
- python3-sphinx
stage-packages:
- coreutils
- iproute2
@ -276,6 +296,7 @@ parts:
- --enable-ldpd
- --enable-fpm
- --enable-protobuf
- --enable-rpki
- --enable-configfile-mask=0640
- --enable-logfile-mask=0640
- --localstatedir=/var/run

View File

@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole,
"Table to configure\n"
"The table number to configure\n")
{
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf,
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct static_vrf *svrf = vrf->info;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface,
return CMD_WARNING_CONFIG_FAILED;
}
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -984,7 +984,7 @@ DEFPY(ip_route,
struct static_vrf *nh_svrf;
const char *flag = NULL;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf,
struct static_vrf *nh_svrf;
const char *flag = NULL;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole,
"Table to configure\n"
"The table number to configure\n")
{
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf,
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct static_vrf *svrf = vrf->info;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface,
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1309,7 +1309,7 @@ DEFPY(ipv6_route,
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
if (table_str && !vrf_is_backend_netns()) {
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;

View File

@ -34,6 +34,7 @@
#include "log.h"
#include "nexthop.h"
#include "nexthop_group.h"
#include "hash.h"
#include "static_vrf.h"
#include "static_routes.h"
@ -43,6 +44,7 @@
/* Zebra structure to hold current status. */
struct zclient *zclient;
static struct hash *static_nht_hash;
static struct interface *zebra_interface_if_lookup(struct stream *s)
{
@ -176,10 +178,16 @@ static void zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT);
}
struct static_nht_data {
struct prefix *nh;
uint32_t refcount;
uint8_t nh_num;
};
static int static_zebra_nexthop_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
struct static_nht_data *nhtd, lookup;
struct zapi_route nhr;
afi_t afi = AFI_IP;
@ -191,6 +199,14 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
if (nhr.prefix.family == AF_INET6)
afi = AFI_IP6;
memset(&lookup, 0, sizeof(lookup));
lookup.nh = &nhr.prefix;
nhtd = hash_lookup(static_nht_hash, &lookup);
if (nhtd)
nhtd->nh_num = nhr.nexthop_num;
static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
return 1;
}
@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
mpls_enabled = cap->mpls_enabled;
}
static unsigned int static_nht_hash_key(void *data)
{
struct static_nht_data *nhtd = data;
return prefix_hash_key(nhtd->nh);
}
static int static_nht_hash_cmp(const void *d1, const void *d2)
{
const struct static_nht_data *nhtd1 = d1;
const struct static_nht_data *nhtd2 = d2;
return prefix_same(nhtd1->nh, nhtd2->nh);
}
static void *static_nht_hash_alloc(void *data)
{
struct static_nht_data *copy = data;
struct static_nht_data *new;
new = XMALLOC(MTYPE_TMP, sizeof(*new));
new->nh = prefix_new();
prefix_copy(new->nh, copy->nh);
new->refcount = 0;
new->nh_num = 0;
return new;
}
static void static_nht_hash_free(void *data)
{
struct static_nht_data *nhtd = data;
prefix_free(nhtd->nh);
XFREE(MTYPE_TMP, nhtd);
}
void static_zebra_nht_register(struct static_route *si, bool reg)
{
struct static_nht_data *nhtd, lookup;
uint32_t cmd;
struct prefix p;
afi_t afi = AFI_IP;
cmd = (reg) ?
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
@ -224,20 +280,48 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = si->addr.ipv4;
afi = AFI_IP;
break;
case STATIC_IPV6_GATEWAY:
case STATIC_IPV6_GATEWAY_IFNAME:
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
p.u.prefix6 = si->addr.ipv6;
afi = AFI_IP6;
break;
}
memset(&lookup, 0, sizeof(lookup));
lookup.nh = &p;
si->nh_registered = reg;
if (reg) {
nhtd = hash_get(static_nht_hash, &lookup,
static_nht_hash_alloc);
nhtd->refcount++;
if (nhtd->refcount > 1) {
static_nht_update(nhtd->nh, nhtd->nh_num,
afi, si->nh_vrf_id);
return;
}
} else {
nhtd = hash_lookup(static_nht_hash, &lookup);
if (!nhtd)
return;
nhtd->refcount--;
if (nhtd->refcount >= 1)
return;
hash_release(static_nht_hash, nhtd);
static_nht_hash_free(nhtd);
}
if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
zlog_warn("%s: Failure to send nexthop to zebra",
__PRETTY_FUNCTION__);
si->nh_registered = reg;
}
extern void static_zebra_route_add(struct route_node *rn,
@ -273,9 +357,10 @@ extern void static_zebra_route_add(struct route_node *rn,
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = si_changed->tag;
}
api.tableid = si_changed->table_id;
zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
if (si_changed->table_id != 0) {
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
api.tableid = si_changed->table_id;
}
for (/*loaded above*/; si; si = si->next) {
api_nh = &api.nexthops[nh_num];
if (si->nh_vrf_id == VRF_UNKNOWN)
@ -372,4 +457,8 @@ void static_zebra_init(void)
zclient->interface_address_delete = interface_address_delete;
zclient->route_notify_owner = route_notify_owner;
zclient->nexthop_update = static_zebra_nexthop_update;
static_nht_hash = hash_create(static_nht_hash_key,
static_nht_hash_cmp,
"Static Nexthop Tracking hash");
}

View File

@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
switch (type) {
case CAPABILITY:
len += 2; /* to cover the OPT-Param header */
__attribute__ ((fallthrough));
_FALLTHROUGH
case OPT_PARAM:
printf("len: %u\n", len);
/* peek_for_as4 wants getp at capibility*/

View File

@ -57,7 +57,7 @@ int main(void)
print_stream(s);
stream_resize(s, stream_get_endp(s));
stream_resize_inplace(&s, stream_get_endp(s));
print_stream(s);

View File

@ -1435,24 +1435,6 @@ DEFUNSH(VTYSH_BGPD,
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_BGPD,
rpki_exit,
rpki_exit_cmd,
"exit",
"Exit current mode and down to previous mode\n")
{
vty->node = CONFIG_NODE;
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_BGPD,
rpki_quit,
rpki_quit_cmd,
"quit",
"Exit current mode and down to previous mode\n")
{
return rpki_exit(self, vty, argc, argv);
}
#endif
DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
@ -1790,6 +1772,7 @@ static int vtysh_exit(struct vty *vty)
case VTY_NODE:
case KEYCHAIN_NODE:
case BFD_NODE:
case RPKI_NODE:
vtysh_execute("end");
vtysh_execute("configure terminal");
vty->node = CONFIG_NODE;
@ -1883,8 +1866,24 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
|| vty->node == BGP_VNC_L2_GROUP_NODE)
vty->node = BGP_NODE;
return CMD_SUCCESS;
}
#if defined(HAVE_RPKI)
DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
"Exit current mode and down to previous mode\n")
{
vtysh_exit(vty);
return CMD_SUCCESS;
}
DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
"Exit current mode and down to previous mode\n")
{
return rpki_exit(self, vty, argc, argv);
}
#endif /* HAVE_RPKI */
DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
"Exit from VRF configuration mode\n")
{

View File

@ -1,78 +0,0 @@
GNOME-PRODUCT-ZEBRA-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY,
OBJECT-IDENTITY
FROM SNMPv2-SMI
gnomeProducts
FROM GNOME-SMI;
zebra MODULE-IDENTITY
LAST-UPDATED "200004250000Z"
ORGANIZATION "GNOME project"
CONTACT-INFO
"GNU Network Object Model Environment project
see http://www.gnome.org for contact persons of a particular
area or subproject of GNOME.
Administrative contact for MIB module:
Jochen Friedrich
Wingertstr. 70/1
68809 Neulussheim
Germany
email: snmp@gnome.org"
DESCRIPTION
"The product registrations for the various zebra subdeamons.
These registrations are guaranteed to be unique and are used
for SMUX registration by default (if not overridden manually)."
::= { gnomeProducts 2 }
zserv OBJECT-IDENTITY
STATUS current
DESCRIPTION
"zserv is part of the zebra project which again is a GNU
endorsed internet routing program.
zserv is the main zebra process which implements routing
entries with the kernel and handles routing updates between
other routing protocols."
::= { zebra 1 }
bgpd OBJECT-IDENTITY
STATUS current
DESCRIPTION
"bgpd is part of the zebra project which again is a GNU
endorsed internet routing program."
::= { zebra 2 }
ripd OBJECT-IDENTITY
STATUS current
DESCRIPTION
"ripd is part of the zebra project which again is a GNU
endorsed internet routing program."
::= { zebra 3 }
ripngd OBJECT-IDENTITY
STATUS current
DESCRIPTION
"ripngd is part of the zebra project which again is a GNU
endorsed internet routing program."
::= { zebra 4 }
ospfd OBJECT-IDENTITY
STATUS current
DESCRIPTION
"ospfd is part of the zebra project which again is a GNU
endorsed internet routing program."
::= { zebra 5 }
ospf6d OBJECT-IDENTITY
STATUS current
DESCRIPTION
"ospf6d is part of the zebra project which again is a GNU
endorsed internet routing program."
::= { zebra 6 }
END

View File

@ -1,53 +0,0 @@
GNOME-SMI DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY,
OBJECT-IDENTITY,
enterprises
FROM SNMPv2-SMI;
gnome MODULE-IDENTITY
LAST-UPDATED "9809010000Z"
ORGANIZATION "GNOME project"
CONTACT-INFO
"GNU Network Object Model Environment project
see http://www.gnome.org for contact persons of a particular
area or subproject of GNOME.
Administrative contact for MIB module:
Jochen Friedrich
Wingertstr. 70/1
68809 Neulussheim
Germany
email: snmp@gnome.org"
DESCRIPTION
"The Structure of GNOME."
::= { enterprises 3317 } -- assigned by IANA
gnomeProducts OBJECT-IDENTITY
STATUS current
DESCRIPTION
"gnomeProducts is the root OBJECT IDENTIFIER from
which sysObjectID values are assigned."
::= { gnome 1 }
gnomeMgmt OBJECT-IDENTITY
STATUS current
DESCRIPTION
"gnomeMgmt defines the subtree for production GNOME related
MIB registrations."
::= { gnome 2 }
gnomeTest OBJECT-IDENTITY
STATUS current
DESCRIPTION
"gnomeTest defines the subtree for testing GNOME related
MIB registrations."
::= { gnome 3 }
-- more to come if necessary.
END

View File

@ -1,208 +0,0 @@
/*
* GNU Zebra client test main routine.
* Copyright (C) 1997 Kunihiro Ishiguro
*
* 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 "prefix.h"
#include "stream.h"
#include "zclient.h"
#include "thread.h"
#include "table.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
struct thread *master;
/* Zebra client structure. */
struct zclient *zclient = NULL;
/* Zebra socket. */
int sock;
/* IPv4 route add and delete test. */
void zebra_test_ipv4(int command, int type, char *prefix, char *gateway,
uint8_t distance)
{
struct zapi_ipv4 api;
struct prefix_ipv4 p;
struct in_addr gate;
struct in_addr *gpnt;
str2prefix_ipv4(prefix, &p);
if (!inet_aton(gateway, &gate)) {
printf("Gateway specified: %s is illegal\n", gateway);
return;
}
gpnt = &gate;
api.vrf_id = VRF_DEFAULT;
api.type = type;
api.flags = 0;
api.message = 0;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 1;
api.nexthop = &gpnt;
api.ifindex_num = 0;
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
}
switch (command) {
case ZEBRA_IPV4_ROUTE_ADD:
zapi_ipv4_add(zclient, &p, &api);
break;
case ZEBRA_IPV4_ROUTE_DELETE:
zapi_ipv4_delete(zclient, &p, &api);
break;
}
}
/* IPv6 route add and delete test. */
void zebra_test_v6(int sock)
{
struct prefix_ipv6 p;
struct in6_addr nexthop;
str2prefix_ipv6("3ffe:506::2/128", &p);
inet_pton(AF_INET6, "::1", &nexthop);
/* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */
sleep(5);
/* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */
}
/* Print out usage and exit. */
void usage_exit()
{
fprintf(stderr, "Usage: client filename\n");
exit(1);
}
struct zebra_info {
char *str;
int type;
} zebra_type[] = {{"static", ZEBRA_ROUTE_STATIC},
{"rip", ZEBRA_ROUTE_RIP},
{"ripng", ZEBRA_ROUTE_RIPNG},
{"ospf", ZEBRA_ROUTE_OSPF},
{"ospf6", ZEBRA_ROUTE_OSPF6},
{"bgp", ZEBRA_ROUTE_BGP},
{"nhrp", ZEBRA_ROUTE_NHRP},
{"pim", ZEBRA_ROUTE_PIM},
{NULL, 0}};
/* Zebra route simulator. */
void zebra_sim(FILE *fp)
{
char buf[BUFSIZ];
char distance_str[BUFSIZ];
uint8_t distance;
while (fgets(buf, sizeof buf, fp)) {
int i;
int ret;
int type;
char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ],
gateway[BUFSIZ];
distance = 0;
if (*buf == '#')
continue;
type = ZEBRA_ROUTE_STATIC;
ret = sscanf(buf, "%s %s %s %s %s\n", command, str, prefix,
gateway, distance_str);
if (ret == 5) {
distance = atoi(distance_str);
} else {
ret = sscanf(buf, "%s %s %s %s\n", command, str, prefix,
gateway);
if (ret != 4)
continue;
}
i = 0;
while (zebra_type[i++].str) {
if (strcmp(zebra_type[i].str, str) == 0) {
type = zebra_type[i].type;
break;
}
}
if (strcmp(command, "add") == 0) {
zebra_test_ipv4(ZEBRA_IPV4_ROUTE_ADD, type, prefix,
gateway, distance);
printf("%s", buf);
continue;
}
if (strcmp(command, "del") == 0) {
zebra_test_ipv4(ZEBRA_IPV4_ROUTE_DELETE, type, prefix,
gateway, distance);
printf("%s", buf);
continue;
}
}
}
/* Test zebra client main routine. */
int main(int argc, char **argv)
{
struct thread_master *master;
FILE *fp;
if (argc == 1)
usage_exit();
master = thread_master_create(NULL);
/* Establish connection to zebra. */
zclient = zclient_new_notify(master, &zclient_options_default);
zclient->enable = 1;
zclient_socket_connect(zclient);
/* Open simulation file. */
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr,
"%% Can't open configuration file %s due to '%s'\n",
argv[1], safe_strerror(errno));
exit(1);
}
/* Do main work. */
zebra_sim(fp);
sleep(100);
fclose(fp);
close(sock);
return 0;
}

View File

@ -37,6 +37,7 @@
#include "zebra/interface.h"
#include "zebra/rib.h"
#include "zebra/rt.h"
#include <ifaddrs.h>

View File

@ -467,6 +467,18 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
}
}
/**
* netlink_parse_rtattr_nested() - Parses a nested route attribute
* @tb: Pointer to array for storing rtattr in.
* @max: Max number to store.
* @rta: Pointer to rtattr to look for nested items in.
*/
void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
struct rtattr *rta)
{
netlink_parse_rtattr(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
}
int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
const void *data, unsigned int alen)
{

View File

@ -28,6 +28,8 @@
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
struct rtattr *rta, int len);
extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
struct rtattr *rta);
extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
const void *data, unsigned int alen);
extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,

View File

@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
return write;
}
void zebra_import_table_rm_update()
void zebra_import_table_rm_update(const char *rmap)
{
afi_t afi;
int i;
@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
continue;
rmap_name = zebra_get_import_table_route_map(afi, i);
if (!rmap_name)
return;
if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
continue;
table = zebra_vrf_other_route_table(afi, i,
VRF_DEFAULT);
for (rn = route_top(table); rn; rn = route_next(rn)) {

View File

@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);
extern int zebra_import_table_config(struct vty *);
extern void zebra_import_table_rm_update(void);
extern void zebra_import_table_rm_update(const char *rmap);
#endif /* _ZEBRA_REDISTRIBUTE_H */

View File

@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
vrf_id_t vrf_id);
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
extern void rib_update_table(struct route_table *table,
rib_update_event_t event);
extern void rib_sweep_route(void);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);

View File

@ -246,6 +246,33 @@ static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
return VRF_DEFAULT;
}
/**
* @parse_encap_mpls() - Parses encapsulated mpls attributes
* @tb: Pointer to rtattr to look for nested items in.
* @labels: Pointer to store labels in.
*
* Return: Number of mpls labels found.
*/
static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
{
struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
mpls_lse_t *lses = NULL;
int num_labels = 0;
uint32_t ttl = 0;
uint32_t bos = 0;
uint32_t exp = 0;
mpls_label_t label = 0;
netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
while (!bos && num_labels < MPLS_MAX_LABELS) {
mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
labels[num_labels++] = label;
}
return num_labels;
}
/* Looking up routing table by netlink interface. */
static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
int startup)
@ -274,6 +301,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
void *src = NULL; /* IPv6 srcdest source prefix */
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
/* MPLS labels */
mpls_label_t labels[MPLS_MAX_LABELS] = {0};
int num_labels = 0;
rtm = NLMSG_DATA(h);
if (startup && h->nlmsg_type != RTM_NEWROUTE)
@ -508,6 +539,17 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
}
nh.vrf_id = nh_vrf_id;
if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
&& *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
== LWTUNNEL_ENCAP_MPLS) {
num_labels =
parse_encap_mpls(tb[RTA_ENCAP], labels);
}
if (num_labels)
nexthop_add_labels(&nh, ZEBRA_LSP_STATIC,
num_labels, labels);
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
&src_p, &nh, table, metric, mtu, distance, tag);
} else {
@ -532,6 +574,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
re->tag = tag;
for (;;) {
struct nexthop *nh = NULL;
vrf_id_t nh_vrf_id;
if (len < (int)sizeof(*rtnh)
|| rtnh->rtnh_len > len)
@ -569,35 +612,46 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (tb[RTA_GATEWAY])
gate = RTA_DATA(
tb[RTA_GATEWAY]);
if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
&& *(uint16_t *)RTA_DATA(
tb[RTA_ENCAP_TYPE])
== LWTUNNEL_ENCAP_MPLS) {
num_labels = parse_encap_mpls(
tb[RTA_ENCAP], labels);
}
}
if (gate) {
if (rtm->rtm_family == AF_INET) {
if (index)
route_entry_nexthop_ipv4_ifindex_add(
nh = route_entry_nexthop_ipv4_ifindex_add(
re, gate,
prefsrc, index,
nh_vrf_id);
else
route_entry_nexthop_ipv4_add(
nh = route_entry_nexthop_ipv4_add(
re, gate,
prefsrc,
nh_vrf_id);
} else if (rtm->rtm_family
== AF_INET6) {
if (index)
route_entry_nexthop_ipv6_ifindex_add(
nh = route_entry_nexthop_ipv6_ifindex_add(
re, gate, index,
nh_vrf_id);
else
route_entry_nexthop_ipv6_add(
nh = route_entry_nexthop_ipv6_add(
re, gate,
nh_vrf_id);
}
} else
route_entry_nexthop_ifindex_add(
nh = route_entry_nexthop_ifindex_add(
re, index, nh_vrf_id);
if (nh && num_labels)
nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
num_labels, labels);
if (rtnh->rtnh_len == 0)
break;

View File

@ -141,13 +141,3 @@ if DEV_BUILD
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
endif
endif
EXTRA_DIST += \
zebra/GNOME-SMI \
zebra/GNOME-PRODUCT-ZEBRA-MIB \
# end
# -- unmaintained --
# noinst_PROGRAMS += zebra/client
# zebra_client_SOURCES = zebra/client_main.c
# zebra_client_LDADD = lib/libfrr.la

View File

@ -1022,6 +1022,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
unsigned short l = 0;
uint8_t flags = 0;
uint16_t type = cmd2type[hdr->command];
bool exist;
if (IS_ZEBRA_DEBUG_NHT)
zlog_debug(
@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
p.family);
return;
}
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
if (!rnh)
return;
if (type == RNH_NEXTHOP_TYPE) {
if (flags
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
@ -1084,7 +1088,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
/* Anything not AF_INET/INET6 has been filtered out above */
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
if (!exist)
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type,
&p);
}
stream_failure:
@ -1584,202 +1590,6 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
}
}
/* This function support multiple nexthop. */
/*
* Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
* add kernel route.
*/
static void zread_ipv4_add(ZAPI_HANDLER_ARGS)
{
int i;
struct route_entry *re;
struct prefix p;
uint8_t message;
struct in_addr nhop_addr;
uint8_t nexthop_num;
uint8_t nexthop_type;
struct stream *s;
ifindex_t ifindex;
safi_t safi;
int ret;
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label;
struct nexthop *nexthop;
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
s = msg;
/* Allocate new re. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
/* Type, flags, message. */
STREAM_GETC(s, re->type);
if (re->type > ZEBRA_ROUTE_MAX) {
zlog_warn("%s: Specified route type %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
STREAM_GETC(s, message);
STREAM_GETW(s, safi);
re->uptime = time(NULL);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
STREAM_GETC(s, p.prefixlen);
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn(
"%s: Specified prefix length %d is greater than what v4 can be",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
/* Nexthop parse. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
STREAM_GETC(s, nexthop_num);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) {
STREAM_GETC(s, nexthop_type);
switch (nexthop_type) {
case NEXTHOP_TYPE_IFINDEX:
STREAM_GETL(s, ifindex);
route_entry_nexthop_ifindex_add(re, ifindex,
re->vrf_id);
break;
case NEXTHOP_TYPE_IPV4:
STREAM_GET(&nhop_addr.s_addr, s,
IPV4_MAX_BYTELEN);
nexthop = route_entry_nexthop_ipv4_add(
re, &nhop_addr, NULL, re->vrf_id);
/*
* For labeled-unicast, each nexthop is followed
* by the label.
*/
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
STREAM_GETL(s, label);
nexthop_add_labels(nexthop, label_type,
1, &label);
}
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
STREAM_GET(&nhop_addr.s_addr, s,
IPV4_MAX_BYTELEN);
STREAM_GETL(s, ifindex);
route_entry_nexthop_ipv4_ifindex_add(
re, &nhop_addr, NULL, ifindex,
re->vrf_id);
break;
case NEXTHOP_TYPE_IPV6:
zlog_warn(
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops",
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
return;
case NEXTHOP_TYPE_BLACKHOLE:
route_entry_nexthop_blackhole_add(re, bh_type);
break;
default:
zlog_warn(
"%s: Specified nexthop type: %d does not exist",
__PRETTY_FUNCTION__, nexthop_type);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
return;
}
}
}
/* Distance. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
STREAM_GETC(s, re->distance);
/* Metric. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
STREAM_GETL(s, re->metric);
/* Tag */
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
STREAM_GETL(s, re->tag);
else
re->tag = 0;
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
STREAM_GETL(s, re->mtu);
else
re->mtu = 0;
/* Table */
re->table = zvrf->table_id;
ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re);
/* Stats */
if (ret > 0)
client->v4_route_add_cnt++;
else if (ret < 0)
client->v4_route_upd8_cnt++;
return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
}
/* Zebra server IPv4 prefix delete function. */
static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_ipv4 api;
struct prefix p;
uint32_t table_id;
s = msg;
/* Type, flags, message. */
STREAM_GETC(s, api.type);
STREAM_GETW(s, api.instance);
STREAM_GETL(s, api.flags);
STREAM_GETC(s, api.message);
STREAM_GETW(s, api.safi);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix));
p.family = AF_INET;
STREAM_GETC(s, p.prefixlen);
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn("%s: Passed in prefixlen %d is impossible",
__PRETTY_FUNCTION__, p.prefixlen);
return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
table_id = zvrf->table_id;
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &p, NULL, NULL, table_id, 0, 0, false);
client->v4_route_del_cnt++;
stream_failure:
return;
}
/* MRIB Nexthop lookup for IPv4. */
static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
{
@ -1794,417 +1604,6 @@ stream_failure:
return;
}
/* Zebra server IPv6 prefix add function. */
static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS)
{
unsigned int i;
struct stream *s;
struct in6_addr nhop_addr;
struct route_entry *re;
uint8_t message;
uint8_t nexthop_num;
uint8_t nexthop_type;
struct prefix p;
safi_t safi;
static struct in6_addr nexthops[MULTIPATH_NUM];
static unsigned int ifindices[MULTIPATH_NUM];
int ret;
static mpls_label_t labels[MULTIPATH_NUM];
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label;
struct nexthop *nexthop;
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
s = msg;
memset(&nhop_addr, 0, sizeof(struct in6_addr));
/* Allocate new re. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
/* Type, flags, message. */
STREAM_GETC(s, re->type);
if (re->type > ZEBRA_ROUTE_MAX) {
zlog_warn("%s: Specified route type: %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
STREAM_GETC(s, message);
STREAM_GETW(s, safi);
re->uptime = time(NULL);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix_ipv4));
p.family = AF_INET;
STREAM_GETC(s, p.prefixlen);
if (p.prefixlen > IPV4_MAX_BITLEN) {
zlog_warn(
"%s: Prefix Length %d is greater than what a v4 address can use",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
/*
* We need to give nh-addr, nh-ifindex with the same next-hop object
* to the re to ensure that IPv6 multipathing works; need to coalesce
* these. Clients should send the same number of paired set of
* next-hop-addr/next-hop-ifindices.
*/
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
unsigned int nh_count = 0;
unsigned int if_count = 0;
unsigned int max_nh_if = 0;
STREAM_GETC(s, nexthop_num);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) {
STREAM_GETC(s, nexthop_type);
switch (nexthop_type) {
case NEXTHOP_TYPE_IPV6:
STREAM_GET(&nhop_addr, s, 16);
if (nh_count < MULTIPATH_NUM) {
/*
* For labeled-unicast, each nexthop is
* followed by the label.
*/
if (CHECK_FLAG(message,
ZAPI_MESSAGE_LABEL)) {
STREAM_GETL(s, label);
labels[nh_count] = label;
}
nexthops[nh_count] = nhop_addr;
nh_count++;
}
break;
case NEXTHOP_TYPE_IFINDEX:
if (if_count < multipath_num)
STREAM_GETL(s, ifindices[if_count++]);
break;
case NEXTHOP_TYPE_BLACKHOLE:
route_entry_nexthop_blackhole_add(re, bh_type);
break;
default:
zlog_warn(
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
return;
}
}
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
for (i = 0; i < max_nh_if; i++) {
if ((i < nh_count)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
if ((i < if_count) && ifindices[i])
nexthop =
route_entry_nexthop_ipv6_ifindex_add(
re, &nexthops[i],
ifindices[i],
re->vrf_id);
else
nexthop = route_entry_nexthop_ipv6_add(
re, &nexthops[i], re->vrf_id);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
nexthop_add_labels(nexthop, label_type,
1, &labels[i]);
} else {
if ((i < if_count) && ifindices[i])
route_entry_nexthop_ifindex_add(
re, ifindices[i], re->vrf_id);
}
}
}
/* Distance. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
STREAM_GETC(s, re->distance);
/* Metric. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
STREAM_GETL(s, re->metric);
/* Tag */
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
STREAM_GETL(s, re->tag);
else
re->tag = 0;
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
STREAM_GETL(s, re->mtu);
else
re->mtu = 0;
/* Table */
re->table = zvrf->table_id;
ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re);
/* Stats */
if (ret > 0)
client->v4_route_add_cnt++;
else if (ret < 0)
client->v4_route_upd8_cnt++;
return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
}
static void zread_ipv6_add(ZAPI_HANDLER_ARGS)
{
unsigned int i;
struct stream *s;
struct in6_addr nhop_addr;
ifindex_t ifindex;
struct route_entry *re;
uint8_t message;
uint8_t nexthop_num;
uint8_t nexthop_type;
struct prefix p;
struct prefix_ipv6 src_p, *src_pp;
safi_t safi;
static struct in6_addr nexthops[MULTIPATH_NUM];
static unsigned int ifindices[MULTIPATH_NUM];
int ret;
static mpls_label_t labels[MULTIPATH_NUM];
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
mpls_label_t label;
struct nexthop *nexthop;
enum blackhole_type bh_type = BLACKHOLE_NULL;
/* Get input stream. */
s = msg;
memset(&nhop_addr, 0, sizeof(struct in6_addr));
/* Allocate new re. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
/* Type, flags, message. */
STREAM_GETC(s, re->type);
if (re->type > ZEBRA_ROUTE_MAX) {
zlog_warn("%s: Specified route type: %d is not a legal value\n",
__PRETTY_FUNCTION__, re->type);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GETW(s, re->instance);
STREAM_GETL(s, re->flags);
STREAM_GETC(s, message);
STREAM_GETW(s, safi);
re->uptime = time(NULL);
/* IPv6 prefix. */
memset(&p, 0, sizeof(p));
p.family = AF_INET6;
STREAM_GETC(s, p.prefixlen);
if (p.prefixlen > IPV6_MAX_BITLEN) {
zlog_warn(
"%s: Specified prefix length %d is to large for v6 prefix",
__PRETTY_FUNCTION__, p.prefixlen);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) {
memset(&src_p, 0, sizeof(src_p));
src_p.family = AF_INET6;
STREAM_GETC(s, src_p.prefixlen);
if (src_p.prefixlen > IPV6_MAX_BITLEN) {
zlog_warn(
"%s: Specified src prefix length %d is to large for v6 prefix",
__PRETTY_FUNCTION__, src_p.prefixlen);
XFREE(MTYPE_RE, re);
return;
}
STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
src_pp = &src_p;
} else
src_pp = NULL;
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
/*
* We need to give nh-addr, nh-ifindex with the same next-hop object
* to the re to ensure that IPv6 multipathing works; need to coalesce
* these. Clients should send the same number of paired set of
* next-hop-addr/next-hop-ifindices.
*/
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
unsigned int nh_count = 0;
unsigned int if_count = 0;
unsigned int max_nh_if = 0;
STREAM_GETC(s, nexthop_num);
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
nexthop_num);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
label_type = lsp_type_from_re_type(client->proto);
for (i = 0; i < nexthop_num; i++) {
STREAM_GETC(s, nexthop_type);
switch (nexthop_type) {
case NEXTHOP_TYPE_IPV6:
STREAM_GET(&nhop_addr, s, 16);
if (nh_count < MULTIPATH_NUM) {
/*
* For labeled-unicast, each nexthop is
* followed by label.
*/
if (CHECK_FLAG(message,
ZAPI_MESSAGE_LABEL)) {
STREAM_GETL(s, label);
labels[nh_count] = label;
}
nexthops[nh_count++] = nhop_addr;
}
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
STREAM_GET(&nhop_addr, s, 16);
STREAM_GETL(s, ifindex);
route_entry_nexthop_ipv6_ifindex_add(
re, &nhop_addr, ifindex, re->vrf_id);
break;
case NEXTHOP_TYPE_IFINDEX:
if (if_count < multipath_num)
STREAM_GETL(s, ifindices[if_count++]);
break;
case NEXTHOP_TYPE_BLACKHOLE:
route_entry_nexthop_blackhole_add(re, bh_type);
break;
default:
zlog_warn(
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
__PRETTY_FUNCTION__);
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
return;
}
}
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
for (i = 0; i < max_nh_if; i++) {
if ((i < nh_count)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
if ((i < if_count) && ifindices[i])
nexthop =
route_entry_nexthop_ipv6_ifindex_add(
re, &nexthops[i],
ifindices[i],
re->vrf_id);
else
nexthop = route_entry_nexthop_ipv6_add(
re, &nexthops[i], re->vrf_id);
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
nexthop_add_labels(nexthop, label_type,
1, &labels[i]);
} else {
if ((i < if_count) && ifindices[i])
route_entry_nexthop_ifindex_add(
re, ifindices[i], re->vrf_id);
}
}
}
/* Distance. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
STREAM_GETC(s, re->distance);
/* Metric. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
STREAM_GETL(s, re->metric);
/* Tag */
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
STREAM_GETL(s, re->tag);
else
re->tag = 0;
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
STREAM_GETL(s, re->mtu);
else
re->mtu = 0;
re->table = zvrf->table_id;
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);
/* Stats */
if (ret > 0)
client->v6_route_add_cnt++;
else if (ret < 0)
client->v6_route_upd8_cnt++;
return;
stream_failure:
nexthops_free(re->ng.nexthop);
XFREE(MTYPE_RE, re);
}
/* Zebra server IPv6 prefix delete function. */
static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_ipv6 api;
struct prefix p;
struct prefix_ipv6 src_p, *src_pp;
s = msg;
/* Type, flags, message. */
STREAM_GETC(s, api.type);
STREAM_GETW(s, api.instance);
STREAM_GETL(s, api.flags);
STREAM_GETC(s, api.message);
STREAM_GETW(s, api.safi);
/* IPv4 prefix. */
memset(&p, 0, sizeof(struct prefix));
p.family = AF_INET6;
STREAM_GETC(s, p.prefixlen);
STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
memset(&src_p, 0, sizeof(struct prefix_ipv6));
src_p.family = AF_INET6;
STREAM_GETC(s, src_p.prefixlen);
STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
src_pp = &src_p;
} else
src_pp = NULL;
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &p, src_pp, NULL, client->rtm_table, 0, 0, false);
client->v6_route_del_cnt++;
stream_failure:
return;
}
/* Register zebra server router-id information. Send current router-id */
static void zread_router_id_add(ZAPI_HANDLER_ARGS)
{
@ -3011,11 +2410,6 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
[ZEBRA_ROUTE_ADD] = zread_route_add,
[ZEBRA_ROUTE_DELETE] = zread_route_del,
[ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add,
[ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete,
[ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add,
[ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add,
[ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete,
[ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
[ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
[ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,

View File

@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
/* filter route selection in following order:
* - connected beats other types
* - if both connected, loopback or vrf wins
* - lower distance beats higher
* - lower metric beats higher for equal distance
* - last, hence oldest, route wins tie break.
*/
/* Connected routes. Pick the last connected
/* Connected routes. Check to see if either are a vrf
* or loopback interface. If not, pick the last connected
* route of the set of lowest metric connected routes.
*/
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
if (current->type != ZEBRA_ROUTE_CONNECT
|| alternate->metric <= current->metric)
if (current->type != ZEBRA_ROUTE_CONNECT)
return alternate;
/* both are connected. are either loop or vrf? */
struct nexthop *nexthop = NULL;
for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
if (if_is_loopback_or_vrf(if_lookup_by_index(
nexthop->ifindex, alternate->vrf_id)))
return alternate;
}
for (ALL_NEXTHOPS(current->ng, nexthop)) {
if (if_is_loopback_or_vrf(if_lookup_by_index(
nexthop->ifindex, current->vrf_id)))
return current;
}
/* Neither are loop or vrf so pick best metric */
if (alternate->metric <= current->metric)
return alternate;
return current;
@ -2651,8 +2671,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
/* Schedule routes of a particular table (address-family) based on event. */
static void rib_update_table(struct route_table *table,
rib_update_event_t event)
void rib_update_table(struct route_table *table, rib_update_event_t event)
{
struct route_node *rn;
struct route_entry *re, *next;
@ -2732,12 +2751,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)
/* Process routes of interested address-families. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
if (table)
if (table) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP event %d", __func__, event);
rib_update_table(table, event);
}
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
if (table)
if (table) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 event %d", __func__, event);
rib_update_table(table, event);
}
}
/* Delete self installed routes after zebra is relaunched. */

View File

@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
return buf;
}
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
bool *exists)
{
struct route_table *table;
struct route_node *rn;
@ -119,6 +120,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
prefix2str(p, buf, sizeof(buf));
zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
buf, type);
exists = false;
return NULL;
}
@ -136,7 +138,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
route_lock_node(rn);
rn->info = rnh;
rnh->node = rn;
}
*exists = false;
} else
*exists = true;
route_unlock_node(rn);
return (rn->info);
@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
route_unlock_node(rn);
}
/*
* This code will send to the registering client
* the looked up rnh.
* For a rnh that was created, there is no data
* so it will send an empty nexthop group
* If rnh exists then we know it has been evaluated
* and as such it will have a resolved rnh.
*/
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_type_t type, vrf_id_t vrf_id)
{
@ -201,8 +213,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
}
if (!listnode_lookup(rnh->client_list, client)) {
listnode_add(rnh->client_list, client);
send_client(rnh, client, type,
vrf_id); // Pending: check if its needed
send_client(rnh, client, type, vrf_id);
}
}
@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
{
struct prefix nh;
struct rnh *rnh;
bool exists;
addr2hostprefix(pw->af, &pw->nexthop, &nh);
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE);
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists);
if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
listnode_add(rnh->zebra_pseudowire_list, pw);
pw->rnh = rnh;

View File

@ -68,7 +68,7 @@ static inline int rnh_resolve_via_default(int family)
}
extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type);
rnh_type_t type, bool *exists);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type);
extern void zebra_free_rnh(struct rnh *rnh);

View File

@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object, afi_t afi)
{
struct prefix_list *plist;
if (type == RMAP_ZEBRA) {
plist = prefix_list_lookup(AFI_IP, (char *)rule);
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL)
return RMAP_NOMATCH;
@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
return RMAP_NOMATCH;
}
static void *route_match_ip_address_prefix_list_compile(const char *arg)
static route_map_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
return (route_match_address_prefix_list(rule, prefix, type, object,
AFI_IP));
}
static void *route_match_address_prefix_list_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
static void route_match_ip_address_prefix_list_free(void *rule)
static void route_match_address_prefix_list_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
"ip address prefix-list", route_match_ip_address_prefix_list,
route_match_ip_address_prefix_list_compile,
route_match_ip_address_prefix_list_free};
route_match_address_prefix_list_compile,
route_match_address_prefix_list_free};
static route_map_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
return (route_match_address_prefix_list(rule, prefix, type, object,
AFI_IP6));
}
static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
"ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
route_match_address_prefix_list_compile,
route_match_address_prefix_list_free};
/* `match ip address prefix-len PREFIXLEN' */
@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = {
"src", route_set_src, route_set_src_compile, route_set_src_free,
};
/* The function checks if the changed routemap specified by parameter rmap
* matches the configured protocol routemaps in proto_rm table. If there is
* a match then rib_update_table() to process the routes.
*/
static void zebra_rib_table_rm_update(const char *rmap)
{
int i = 0;
struct route_table *table;
char *rmap_name;
char afi_ip = 0;
char afi_ipv6 = 0;
for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
/* Check for ip routemap table */
rmap_name = proto_rm[AFI_IP][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP rmap %s, route type %s",
__func__, rmap, zebra_route_string(i));
/* There is single rib table for all protocols */
if (afi_ip == 0) {
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST,
VRF_DEFAULT);
if (table) {
afi_ip = 1;
rib_update_table(table,
RIB_UPDATE_RMAP_CHANGE);
}
}
}
/* Check for ipv6 routemap table */
rmap_name = proto_rm[AFI_IP6][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 rmap %s,route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ipv6 == 0) {
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST,
VRF_DEFAULT);
if (table) {
afi_ipv6 = 1;
rib_update_table(table,
RIB_UPDATE_RMAP_CHANGE);
}
}
}
}
}
/* The function checks if the changed routemap specified by parameter rmap
* matches the configured protocol routemaps in nht_rm table. If there is
* a match then zebra_evaluate_rnh() to process the nexthops.
*/
static void zebra_nht_rm_update(const char *rmap)
{
int i = 0;
char *rmap_name;
char afi_ip = 0;
char afi_ipv6 = 0;
for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
rmap_name = nht_rm[AFI_IP][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP rmap %s route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ip == 0) {
afi_ip = 1;
zebra_evaluate_rnh(0, AF_INET, 1,
RNH_NEXTHOP_TYPE, NULL);
}
}
rmap_name = nht_rm[AFI_IP6][i];
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s : AFI_IP6 rmap %s route type %s",
__func__, rmap, zebra_route_string(i));
if (afi_ipv6 == 0) {
afi_ipv6 = 1;
zebra_evaluate_rnh(0, AF_INET6, 1,
RNH_NEXTHOP_TYPE, NULL);
}
}
}
}
static void zebra_route_map_process_update_cb(char *rmap_name)
{
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("Event handler for route-map: %s",
rmap_name);
zebra_import_table_rm_update(rmap_name);
zebra_rib_table_rm_update(rmap_name);
zebra_nht_rm_update(rmap_name);
}
static int zebra_route_map_update_timer(struct thread *thread)
@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
* 1) VRF Aware <sigh>
* 2) Route-map aware
*/
zebra_import_table_rm_update();
rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
return (0);
}
@ -1555,12 +1660,19 @@ void zebra_route_map_init()
route_map_match_tag_hook(generic_match_add);
route_map_no_match_tag_hook(generic_match_delete);
route_map_match_ipv6_address_hook(generic_match_add);
route_map_no_match_ipv6_address_hook(generic_match_delete);
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
route_map_install_match(&route_match_tag_cmd);
route_map_install_match(&route_match_interface_cmd);
route_map_install_match(&route_match_ip_next_hop_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_prefix_len_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);

Some files were not shown because too many files have changed in this diff Show More