mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:37:21 +00:00
Merge remote-tracking branch 'upstream/master' into evpn-extended-mobility
Conflicts: zebra/zebra_vxlan.c
This commit is contained in:
commit
f190902f52
@ -4896,6 +4896,23 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
|
|||||||
UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
|
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.
|
* Lookup VNI.
|
||||||
*/
|
*/
|
||||||
|
@ -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,
|
extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi,
|
||||||
struct ipaddr *originator_ip);
|
struct ipaddr *originator_ip);
|
||||||
extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es);
|
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 */
|
#endif /* _BGP_EVPN_PRIVATE_H */
|
||||||
|
@ -1888,6 +1888,14 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
|
|||||||
|
|
||||||
vpn = bgp_evpn_lookup_vni(bgp, vni);
|
vpn = bgp_evpn_lookup_vni(bgp, vni);
|
||||||
if (!vpn) {
|
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
|
/* tenant vrf will be updated when we get local_vni_add from
|
||||||
* zebra
|
* zebra
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
|
|||||||
|
|
||||||
if (BGP_DEBUG(flowspec, FLOWSPEC)) {
|
if (BGP_DEBUG(flowspec, FLOWSPEC)) {
|
||||||
char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
|
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 ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
|
||||||
char *s = NULL;
|
char *s = NULL;
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
|||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct bgp_pbr_match_entry *bpme;
|
struct bgp_pbr_match_entry *bpme;
|
||||||
struct bgp_pbr_match *bpm;
|
struct bgp_pbr_match *bpm;
|
||||||
int unit = 0;
|
bool list_began = false;
|
||||||
struct list *list_bpm;
|
struct list *list_bpm;
|
||||||
|
|
||||||
list_bpm = list_new();
|
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))
|
if (listnode_lookup(list_bpm, bpm))
|
||||||
continue;
|
continue;
|
||||||
listnode_add(list_bpm, bpm);
|
listnode_add(list_bpm, bpm);
|
||||||
if (unit == 0)
|
if (!list_began) {
|
||||||
vty_out(vty, " (");
|
vty_out(vty, " (");
|
||||||
else
|
list_began = true;
|
||||||
|
} else
|
||||||
vty_out(vty, ", ");
|
vty_out(vty, ", ");
|
||||||
vty_out(vty, "%s", bpm->ipset_name);
|
vty_out(vty, "%s", bpm->ipset_name);
|
||||||
unit++;
|
|
||||||
}
|
}
|
||||||
if (unit)
|
if (list_began)
|
||||||
vty_out(vty, ")");
|
vty_out(vty, ")");
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
list_delete_and_null(&list_bpm);
|
list_delete_and_null(&list_bpm);
|
||||||
|
@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
|
|||||||
listener->fd = sock;
|
listener->fd = sock;
|
||||||
|
|
||||||
/* this socket needs a change of ns. record bgp back pointer */
|
/* 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;
|
listener->bgp = bgp;
|
||||||
|
|
||||||
memcpy(&listener->su, sa, salen);
|
memcpy(&listener->su, sa, salen);
|
||||||
|
@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
|
|||||||
? "!" : "",
|
? "!" : "",
|
||||||
bpf->dscp->val);
|
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",
|
add ? "adding" : "removing",
|
||||||
bpf->src == NULL ? "<all>" :
|
bpf->src == NULL ? "<all>" :
|
||||||
prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
|
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);
|
bgp_pbr_match_alloc_intern);
|
||||||
|
|
||||||
/* new, then self allocate ipset_name and unique */
|
/* new, then self allocate ipset_name and unique */
|
||||||
if (bpm && bpm->unique == 0) {
|
if (bpm->unique == 0) {
|
||||||
bpm->unique = ++bgp_pbr_match_counter_unique;
|
bpm->unique = ++bgp_pbr_match_counter_unique;
|
||||||
/* 0 value is forbidden */
|
/* 0 value is forbidden */
|
||||||
sprintf(bpm->ipset_name, "match%p", bpm);
|
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.src_port_max = src_port ? src_port->max_port : 0;
|
||||||
temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
|
temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
|
||||||
temp2.proto = bpf->protocol;
|
temp2.proto = bpf->protocol;
|
||||||
if (bpm)
|
bpme = hash_get(bpm->entry_hash, &temp2,
|
||||||
bpme = hash_get(bpm->entry_hash, &temp2,
|
bgp_pbr_match_entry_alloc_intern);
|
||||||
bgp_pbr_match_entry_alloc_intern);
|
if (bpme->unique == 0) {
|
||||||
if (bpme && bpme->unique == 0) {
|
|
||||||
bpme->unique = ++bgp_pbr_match_entry_counter_unique;
|
bpme->unique = ++bgp_pbr_match_entry_counter_unique;
|
||||||
/* 0 value is forbidden */
|
/* 0 value is forbidden */
|
||||||
bpme->backpointer = bpm;
|
bpme->backpointer = bpm;
|
||||||
@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
|||||||
bpme_found = true;
|
bpme_found = true;
|
||||||
|
|
||||||
/* already installed */
|
/* already installed */
|
||||||
if (bpme_found && bpme) {
|
if (bpme_found) {
|
||||||
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
|
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
|
||||||
|
|
||||||
if (extra && extra->bgp_fs_pbr &&
|
if (extra && extra->bgp_fs_pbr &&
|
||||||
|
130
bgpd/bgp_route.c
130
bgpd/bgp_route.c
@ -38,6 +38,7 @@
|
|||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "lib/json.h"
|
#include "lib/json.h"
|
||||||
|
#include "lib_errors.h"
|
||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_table.h"
|
#include "bgpd/bgp_table.h"
|
||||||
@ -188,8 +189,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
|
|||||||
if (e->parent) {
|
if (e->parent) {
|
||||||
struct bgp_info *bi = (struct bgp_info *)e->parent;
|
struct bgp_info *bi = (struct bgp_info *)e->parent;
|
||||||
|
|
||||||
if (bi->net)
|
if (bi->net) {
|
||||||
bi->net = bgp_unlock_node((struct bgp_node *)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);
|
bgp_info_unlock(e->parent);
|
||||||
e->parent = NULL;
|
e->parent = NULL;
|
||||||
}
|
}
|
||||||
@ -198,8 +215,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
|
|||||||
bgp_unlock(e->bgp_orig);
|
bgp_unlock(e->bgp_orig);
|
||||||
|
|
||||||
if ((*extra)->bgp_fs_pbr)
|
if ((*extra)->bgp_fs_pbr)
|
||||||
list_delete_all_node((*extra)->bgp_fs_pbr);
|
list_delete_and_null(&((*extra)->bgp_fs_pbr));
|
||||||
(*extra)->bgp_fs_pbr = NULL;
|
|
||||||
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
|
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
|
||||||
|
|
||||||
*extra = NULL;
|
*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. */
|
/* slight hack, but more robust against errors. */
|
||||||
if (ri->peer->pcount[table->afi][table->safi])
|
if (ri->peer->pcount[table->afi][table->safi])
|
||||||
ri->peer->pcount[table->afi][table->safi]--;
|
ri->peer->pcount[table->afi][table->safi]--;
|
||||||
else {
|
else
|
||||||
zlog_warn(
|
flog_err(LIB_ERR_DEVELOPMENT,
|
||||||
"%s: Asked to decrement 0 prefix count for peer %s",
|
"Asked to decrement 0 prefix count for peer");
|
||||||
__func__, ri->peer->host);
|
|
||||||
zlog_backtrace(LOG_WARNING);
|
|
||||||
zlog_warn("%s: Please report to Quagga bugzilla",
|
|
||||||
__func__);
|
|
||||||
}
|
|
||||||
} else if (BGP_INFO_COUNTABLE(ri)
|
} else if (BGP_INFO_COUNTABLE(ri)
|
||||||
&& !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
&& !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
||||||
SET_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) \
|
#define FILTER_EXIST_WARN(F, f, filter) \
|
||||||
if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
|
if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
|
||||||
zlog_warn("%s: Could not find configured input %s-list %s!", \
|
zlog_debug("%s: Could not find configured input %s-list %s!", \
|
||||||
peer->host, #f, F##_IN_NAME(filter));
|
peer->host, #f, F##_IN_NAME(filter));
|
||||||
|
|
||||||
if (DISTRIBUTE_IN_NAME(filter)) {
|
if (DISTRIBUTE_IN_NAME(filter)) {
|
||||||
FILTER_EXIST_WARN(DISTRIBUTE, distribute, 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) \
|
#define FILTER_EXIST_WARN(F, f, filter) \
|
||||||
if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
|
if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
|
||||||
zlog_warn("%s: Could not find configured output %s-list %s!", \
|
zlog_debug("%s: Could not find configured output %s-list %s!", \
|
||||||
peer->host, #f, F##_OUT_NAME(filter));
|
peer->host, #f, F##_OUT_NAME(filter));
|
||||||
|
|
||||||
if (DISTRIBUTE_OUT_NAME(filter)) {
|
if (DISTRIBUTE_OUT_NAME(filter)) {
|
||||||
FILTER_EXIST_WARN(DISTRIBUTE, distribute, 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\" : {");
|
vty_out(vty, " \"routeDistinguishers\" : {");
|
||||||
++*json_header_depth;
|
++*json_header_depth;
|
||||||
}
|
}
|
||||||
json_paths = json_object_new_object();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_json && rd) {
|
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;
|
*total_cum = total_count;
|
||||||
}
|
}
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
if (json_paths)
|
|
||||||
json_object_free(json_paths);
|
|
||||||
if (rd) {
|
if (rd) {
|
||||||
vty_out(vty, " }%s ", (is_last ? "" : ","));
|
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 count = 0;
|
||||||
int best = 0;
|
int best = 0;
|
||||||
int suppress = 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_export = 0;
|
||||||
int no_advertise = 0;
|
int no_advertise = 0;
|
||||||
int local_as = 0;
|
int local_as = 0;
|
||||||
|
int no_peer = 0;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
int has_valid_label = 0;
|
int has_valid_label = 0;
|
||||||
mpls_label_t label = 0;
|
mpls_label_t label = 0;
|
||||||
@ -8652,12 +8670,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
|||||||
} else
|
} else
|
||||||
vty_out(vty, ", no best path");
|
vty_out(vty, ", no best path");
|
||||||
|
|
||||||
if (no_advertise)
|
if (accept_own)
|
||||||
vty_out(vty, ", not advertised to any peer");
|
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)
|
else if (no_export)
|
||||||
vty_out(vty, ", not advertised to EBGP peer");
|
vty_out(vty, ", not advertised to EBGP peer");
|
||||||
|
else if (no_advertise)
|
||||||
|
vty_out(vty, ", not advertised to any peer");
|
||||||
else if (local_as)
|
else if (local_as)
|
||||||
vty_out(vty, ", not advertised outside 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)
|
if (suppress)
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
@ -9018,6 +9065,10 @@ DEFUN (show_ip_bgp,
|
|||||||
|prefix-list WORD\
|
|prefix-list WORD\
|
||||||
|filter-list WORD\
|
|filter-list WORD\
|
||||||
|statistics\
|
|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]\
|
|community-list <(1-500)|WORD> [exact-match]\
|
||||||
|A.B.C.D/M longer-prefixes\
|
|A.B.C.D/M longer-prefixes\
|
||||||
|X:X::X:X/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"
|
"Display routes conforming to the filter-list\n"
|
||||||
"Regular expression access list name\n"
|
"Regular expression access list name\n"
|
||||||
"BGP RIB advertisement statistics\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"
|
"Display routes matching the community-list\n"
|
||||||
"community-list number\n"
|
"community-list number\n"
|
||||||
"community-list name\n"
|
"community-list name\n"
|
||||||
@ -9797,8 +9865,6 @@ static int bgp_peer_count_walker(struct thread *t)
|
|||||||
pc->count[PCOUNT_ADJ_IN]++;
|
pc->count[PCOUNT_ADJ_IN]++;
|
||||||
|
|
||||||
for (ri = rn->info; ri; ri = ri->next) {
|
for (ri = rn->info; ri; ri = ri->next) {
|
||||||
char buf[SU_ADDRSTRLEN];
|
|
||||||
|
|
||||||
if (ri->peer != peer)
|
if (ri->peer != peer)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -9820,22 +9886,12 @@ static int bgp_peer_count_walker(struct thread *t)
|
|||||||
if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
||||||
pc->count[PCOUNT_COUNTED]++;
|
pc->count[PCOUNT_COUNTED]++;
|
||||||
if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
||||||
zlog_warn(
|
flog_err(LIB_ERR_DEVELOPMENT,
|
||||||
"%s [pcount] %s/%d is counted but flags 0x%x",
|
"Attempting to count but flags say it is unusable");
|
||||||
peer->host,
|
|
||||||
inet_ntop(rn->p.family,
|
|
||||||
&rn->p.u.prefix, buf,
|
|
||||||
SU_ADDRSTRLEN),
|
|
||||||
rn->p.prefixlen, ri->flags);
|
|
||||||
} else {
|
} else {
|
||||||
if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
||||||
zlog_warn(
|
flog_err(LIB_ERR_DEVELOPMENT,
|
||||||
"%s [pcount] %s/%d not counted but flags 0x%x",
|
"Not counted but flags say we should");
|
||||||
peer->host,
|
|
||||||
inet_ntop(rn->p.family,
|
|
||||||
&rn->p.u.prefix, buf,
|
|
||||||
SU_ADDRSTRLEN),
|
|
||||||
rn->p.prefixlen, ri->flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
129
bgpd/bgp_rpki.c
129
bgpd/bgp_rpki.c
@ -47,6 +47,7 @@
|
|||||||
#include "bgpd/bgp_attr.h"
|
#include "bgpd/bgp_attr.h"
|
||||||
#include "bgpd/bgp_aspath.h"
|
#include "bgpd/bgp_aspath.h"
|
||||||
#include "bgpd/bgp_route.h"
|
#include "bgpd/bgp_route.h"
|
||||||
|
#include "lib/network.h"
|
||||||
#include "lib/thread.h"
|
#include "lib/thread.h"
|
||||||
#include "rtrlib/rtrlib.h"
|
#include "rtrlib/rtrlib.h"
|
||||||
#include "rtrlib/rtr_mgr.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 *route_match_compile(const char *arg);
|
||||||
static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
|
static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
|
||||||
safi_t safi);
|
safi_t safi);
|
||||||
|
static void revalidate_all_routes(void);
|
||||||
|
|
||||||
static struct rtr_mgr_config *rtr_config;
|
static struct rtr_mgr_config *rtr_config;
|
||||||
static struct list *cache_list;
|
static struct list *cache_list;
|
||||||
static int rtr_is_running;
|
static int rtr_is_running;
|
||||||
static int rtr_is_stopping;
|
static int rtr_is_stopping;
|
||||||
static int rtr_is_starting;
|
static int rtr_is_starting;
|
||||||
|
static _Atomic int rtr_update_overflow;
|
||||||
static int rpki_debug;
|
static int rpki_debug;
|
||||||
static unsigned int polling_period;
|
static unsigned int polling_period;
|
||||||
static unsigned int expire_interval;
|
static unsigned int expire_interval;
|
||||||
@ -229,7 +232,7 @@ static void *route_match_compile(const char *arg)
|
|||||||
{
|
{
|
||||||
int *rpki_status;
|
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)
|
if (strcmp(arg, "valid") == 0)
|
||||||
*rpki_status = RPKI_VALID;
|
*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,
|
thread_add_read(bm->master, bgpd_sync_callback, NULL,
|
||||||
rpki_sync_socket_bgpd, 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 =
|
int retval =
|
||||||
read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
|
read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
|
||||||
if (retval != 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;
|
afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
|
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++) {
|
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
|
||||||
if (!bgp->rib[afi][safi])
|
safi_t safi;
|
||||||
continue;
|
|
||||||
|
|
||||||
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,
|
matches->del =
|
||||||
rec.max_len, matches);
|
(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))
|
for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
|
||||||
revalidate_bgp_node(bgp_node, afi, safi);
|
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;
|
label = bgp_info->extra->label;
|
||||||
num_labels = bgp_info->extra->num_labels;
|
num_labels = bgp_info->extra->num_labels;
|
||||||
}
|
}
|
||||||
ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi,
|
ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id,
|
||||||
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
|
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
|
||||||
label, num_labels, 1, NULL);
|
BGP_ROUTE_NORMAL, NULL, label, num_labels, 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
bgp_unlock_node(bgp_node);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,25 +438,23 @@ static void revalidate_all_routes(void)
|
|||||||
{
|
{
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct bgp_node *bgp_node;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
|
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
|
||||||
for (size_t i = 0; i < 2; i++) {
|
struct peer *peer;
|
||||||
safi_t safi;
|
struct listnode *peer_listnode;
|
||||||
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
|
|
||||||
|
|
||||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
|
||||||
if (!bgp->rib[afi][safi])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (bgp_node =
|
for (size_t i = 0; i < 2; i++) {
|
||||||
bgp_table_top(bgp->rib[afi][safi]);
|
safi_t safi;
|
||||||
bgp_node;
|
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
|
||||||
bgp_node = bgp_route_next(bgp_node)) {
|
|
||||||
if (bgp_node->info != NULL) {
|
for (safi = SAFI_UNICAST; safi < SAFI_MAX;
|
||||||
revalidate_bgp_node(bgp_node,
|
safi++) {
|
||||||
afi, 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 struct pfx_record rec,
|
||||||
const bool added __attribute__((unused)))
|
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;
|
return;
|
||||||
|
|
||||||
int retval =
|
int retval =
|
||||||
write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
|
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");
|
RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpki_init_sync_socket(void)
|
static void rpki_init_sync_socket(void)
|
||||||
{
|
{
|
||||||
int fds[2];
|
int fds[2];
|
||||||
|
const char *msg;
|
||||||
|
|
||||||
RPKI_DEBUG("initializing sync socket");
|
RPKI_DEBUG("initializing sync socket");
|
||||||
if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
|
if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
|
||||||
RPKI_DEBUG("Could not open rpki sync socket");
|
msg = "could not open rpki sync socketpair";
|
||||||
return;
|
goto err;
|
||||||
}
|
}
|
||||||
rpki_sync_socket_rtr = fds[0];
|
rpki_sync_socket_rtr = fds[0];
|
||||||
rpki_sync_socket_bgpd = fds[1];
|
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,
|
thread_add_read(bm->master, bgpd_sync_callback, NULL,
|
||||||
rpki_sync_socket_bgpd, NULL);
|
rpki_sync_socket_bgpd, NULL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
zlog_err("RPKI: %s", msg);
|
||||||
|
abort();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_rpki_init(struct thread_master *master)
|
static int bgp_rpki_init(struct thread_master *master)
|
||||||
@ -514,6 +562,7 @@ static int start(void)
|
|||||||
|
|
||||||
rtr_is_stopping = 0;
|
rtr_is_stopping = 0;
|
||||||
rtr_is_starting = 1;
|
rtr_is_starting = 1;
|
||||||
|
rtr_update_overflow = 0;
|
||||||
|
|
||||||
if (list_isempty(cache_list)) {
|
if (list_isempty(cache_list)) {
|
||||||
RPKI_DEBUG(
|
RPKI_DEBUG(
|
||||||
@ -1210,10 +1259,10 @@ DEFUN_NOSH (rpki_exit,
|
|||||||
"exit",
|
"exit",
|
||||||
"Exit rpki configuration and restart rpki session\n")
|
"Exit rpki configuration and restart rpki session\n")
|
||||||
{
|
{
|
||||||
int ret = reset(false);
|
reset(false);
|
||||||
|
|
||||||
vty->node = CONFIG_NODE;
|
vty->node = CONFIG_NODE;
|
||||||
return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN_NOSH (rpki_quit,
|
DEFUN_NOSH (rpki_quit,
|
||||||
|
@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
|
|||||||
/*
|
/*
|
||||||
* bgp_unlock_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
293
bgpd/bgp_vty.c
293
bgpd/bgp_vty.c
@ -2019,7 +2019,7 @@ DEFUN (no_bgp_fast_external_failover,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* "bgp enforce-first-as" configuration. */
|
/* "bgp enforce-first-as" configuration. */
|
||||||
#if CONFDATE > 20180517
|
#if CONFDATE > 20190517
|
||||||
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
|
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -10995,7 +10995,7 @@ DEFUN (show_ip_bgp_attr_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
|
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 bgp *bgp;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
@ -11004,64 +11004,148 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
|
|||||||
char *ecom_str;
|
char *ecom_str;
|
||||||
vpn_policy_direction_t dir;
|
vpn_policy_direction_t dir;
|
||||||
|
|
||||||
if (name) {
|
if (use_json) {
|
||||||
bgp = bgp_lookup_by_name(name);
|
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) {
|
if (!bgp) {
|
||||||
vty_out(vty, "%% No such BGP instance exist\n");
|
vty_out(vty, "%% No such BGP instance exist\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
bgp = bgp_get_default();
|
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
if (!bgp) {
|
BGP_CONFIG_VRF_TO_VRF_IMPORT))
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% Default BGP instance does not exist\n");
|
"This VRF is not importing %s routes from any other VRF\n",
|
||||||
return CMD_WARNING;
|
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],
|
for (ALL_LIST_ELEMENTS_RO(
|
||||||
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
|
bgp->vpn_policy[afi].import_vrf,
|
||||||
vty_out(vty,
|
node, vname))
|
||||||
"This VRF is not importing %s routes from any other VRF\n",
|
vty_out(vty, " %s\n", vname);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
dir = BGP_VPN_POLICY_DIR_FROMVPN;
|
||||||
BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
|
ecom_str = ecommunity_ecom2str(
|
||||||
vty_out(vty,
|
bgp->vpn_policy[afi].rtlist[dir],
|
||||||
"This VRF is not exporting %s routes to any other VRF\n",
|
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||||
afi_safi_print(afi, safi));
|
vty_out(vty, "Import RT(s): %s\n", ecom_str);
|
||||||
} else {
|
|
||||||
vty_out(vty,
|
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||||
"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,
|
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
vname)) {
|
BGP_CONFIG_VRF_TO_VRF_EXPORT))
|
||||||
vty_out(vty, " %s\n", vname);
|
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;
|
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. */
|
/* "show [ip] bgp route-leak" command. */
|
||||||
DEFUN (show_ip_bgp_route_leak,
|
DEFUN (show_ip_bgp_route_leak,
|
||||||
show_ip_bgp_route_leak_cmd,
|
show_ip_bgp_route_leak_cmd,
|
||||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak",
|
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
BGP_INSTANCE_HELP_STR
|
BGP_INSTANCE_HELP_STR
|
||||||
BGP_AFI_HELP_STR
|
BGP_AFI_HELP_STR
|
||||||
BGP_SAFI_HELP_STR
|
BGP_SAFI_HELP_STR
|
||||||
"Route leaking information\n")
|
"Route leaking information\n"
|
||||||
|
JSON_STR)
|
||||||
{
|
{
|
||||||
char *vrf = NULL;
|
char *vrf = NULL;
|
||||||
afi_t afi = AFI_MAX;
|
afi_t afi = AFI_MAX;
|
||||||
safi_t safi = SAFI_MAX;
|
safi_t safi = SAFI_MAX;
|
||||||
|
|
||||||
|
uint8_t uj = use_json(argc, argv);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
/* show [ip] bgp */
|
/* show [ip] bgp */
|
||||||
@ -11110,7 +11196,7 @@ DEFUN (show_ip_bgp_route_leak,
|
|||||||
return CMD_WARNING;
|
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,
|
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);
|
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(
|
ALIAS_HIDDEN(
|
||||||
@ -11483,6 +11569,7 @@ DEFUN (bgp_redistribute_ipv4_rmap,
|
|||||||
int idx_word = 3;
|
int idx_word = 3;
|
||||||
int type;
|
int type;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11491,8 +11578,8 @@ DEFUN (bgp_redistribute_ipv4_rmap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(
|
ALIAS_HIDDEN(
|
||||||
@ -11516,6 +11603,7 @@ DEFUN (bgp_redistribute_ipv4_metric,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11525,8 +11613,8 @@ DEFUN (bgp_redistribute_ipv4_metric,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(
|
ALIAS_HIDDEN(
|
||||||
@ -11553,6 +11641,7 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11562,9 +11651,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(
|
ALIAS_HIDDEN(
|
||||||
@ -11595,6 +11684,7 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11604,9 +11694,9 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(
|
ALIAS_HIDDEN(
|
||||||
@ -11642,7 +11732,7 @@ DEFUN (bgp_redistribute_ipv4_ospf,
|
|||||||
protocol = ZEBRA_ROUTE_TABLE;
|
protocol = ZEBRA_ROUTE_TABLE;
|
||||||
|
|
||||||
bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
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,
|
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;
|
struct bgp_redist *red;
|
||||||
unsigned short instance;
|
unsigned short instance;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||||
protocol = ZEBRA_ROUTE_OSPF;
|
protocol = ZEBRA_ROUTE_OSPF;
|
||||||
@ -11677,8 +11768,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
|
|||||||
|
|
||||||
instance = strtoul(argv[idx_number]->arg, NULL, 10);
|
instance = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
|
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
|
||||||
@ -11709,6 +11800,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
|
|||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
unsigned short instance;
|
unsigned short instance;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||||
protocol = ZEBRA_ROUTE_OSPF;
|
protocol = ZEBRA_ROUTE_OSPF;
|
||||||
@ -11719,8 +11811,9 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
|
|||||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
metric);
|
||||||
|
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
|
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
|
||||||
@ -11754,6 +11847,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
|
|||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
unsigned short instance;
|
unsigned short instance;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||||
protocol = ZEBRA_ROUTE_OSPF;
|
protocol = ZEBRA_ROUTE_OSPF;
|
||||||
@ -11764,9 +11858,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
|
|||||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
metric);
|
||||||
|
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALIAS_HIDDEN(
|
ALIAS_HIDDEN(
|
||||||
@ -11803,6 +11898,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
|
|||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
unsigned short instance;
|
unsigned short instance;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||||
protocol = ZEBRA_ROUTE_OSPF;
|
protocol = ZEBRA_ROUTE_OSPF;
|
||||||
@ -11813,9 +11909,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
|
|||||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
metric);
|
||||||
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(
|
ALIAS_HIDDEN(
|
||||||
@ -11923,7 +12020,7 @@ DEFUN (bgp_redistribute_ipv6,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bgp_redist_add(bgp, AFI_IP6, type, 0);
|
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,
|
DEFUN (bgp_redistribute_ipv6_rmap,
|
||||||
@ -11939,6 +12036,7 @@ DEFUN (bgp_redistribute_ipv6_rmap,
|
|||||||
int idx_word = 3;
|
int idx_word = 3;
|
||||||
int type;
|
int type;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11947,8 +12045,8 @@ DEFUN (bgp_redistribute_ipv6_rmap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_metric,
|
DEFUN (bgp_redistribute_ipv6_metric,
|
||||||
@ -11965,6 +12063,7 @@ DEFUN (bgp_redistribute_ipv6_metric,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -11974,8 +12073,8 @@ DEFUN (bgp_redistribute_ipv6_metric,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
||||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
||||||
@ -11995,6 +12094,7 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -12004,9 +12104,10 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type,
|
||||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
metric);
|
||||||
|
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
||||||
@ -12026,6 +12127,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
|||||||
int type;
|
int type;
|
||||||
uint32_t metric;
|
uint32_t metric;
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||||
if (type < 0) {
|
if (type < 0) {
|
||||||
@ -12035,9 +12137,10 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
|||||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||||
|
|
||||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric);
|
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST,
|
||||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
metric);
|
||||||
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 (no_bgp_redistribute_ipv6,
|
DEFUN (no_bgp_redistribute_ipv6,
|
||||||
|
@ -1576,8 +1576,14 @@ static void bgp_redist_del(struct bgp *bgp, afi_t afi, uint8_t type,
|
|||||||
|
|
||||||
/* Other routes redistribution into BGP. */
|
/* Other routes redistribution into BGP. */
|
||||||
int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
|
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. */
|
/* Return if already redistribute flag is set. */
|
||||||
if (instance) {
|
if (instance) {
|
||||||
|
@ -51,7 +51,8 @@ extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t,
|
|||||||
unsigned short);
|
unsigned short);
|
||||||
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
|
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
|
||||||
unsigned short);
|
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_resend(struct bgp *, afi_t, int, unsigned short);
|
||||||
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
|
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
|
||||||
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
|
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
|
||||||
|
22
bgpd/bgpd.c
22
bgpd/bgpd.c
@ -3187,15 +3187,16 @@ int bgp_delete(struct bgp *bgp)
|
|||||||
.import_redirect_rtlist);
|
.import_redirect_rtlist);
|
||||||
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
|
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 */
|
/* Deregister from Zebra, if needed */
|
||||||
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
||||||
bgp_zebra_instance_deregister(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. */
|
/* Free interfaces in this instance. */
|
||||||
bgp_if_finish(bgp);
|
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;
|
time_t uptime1, epoch_tbuf;
|
||||||
struct tm *tm;
|
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 there is no connection has been done before print `never'. */
|
||||||
if (uptime2 == 0) {
|
if (uptime2 == 0) {
|
||||||
if (use_json) {
|
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 */
|
/* clang-format off */
|
||||||
#if CONFDATE > 20180517
|
#if CONFDATE > 20190517
|
||||||
CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
|
CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
|
||||||
#endif
|
#endif
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
13
configure.ac
13
configure.ac
@ -382,7 +382,7 @@ AC_ARG_ENABLE(bgp-vnc,
|
|||||||
AC_ARG_WITH(rfp-path,
|
AC_ARG_WITH(rfp-path,
|
||||||
AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
|
AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
|
||||||
AC_ARG_ENABLE(snmp,
|
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,
|
AC_ARG_ENABLE(zeromq,
|
||||||
AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
|
AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
|
||||||
AC_ARG_WITH(libpam,
|
AC_ARG_WITH(libpam,
|
||||||
@ -418,8 +418,6 @@ AC_ARG_ENABLE(rusage,
|
|||||||
AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
|
AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
|
||||||
AC_ARG_ENABLE(gcc_ultra_verbose,
|
AC_ARG_ENABLE(gcc_ultra_verbose,
|
||||||
AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings]))
|
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,
|
AC_ARG_ENABLE(backtrace,
|
||||||
AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
|
AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
|
||||||
AC_ARG_ENABLE(time-check,
|
AC_ARG_ENABLE(time-check,
|
||||||
@ -644,10 +642,6 @@ AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
|
|||||||
# End of logic for protobuf support.
|
# 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)
|
AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements)
|
||||||
if test "${enable_rtadv}" != "no"; then
|
if test "${enable_rtadv}" != "no"; then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
@ -1496,14 +1490,13 @@ int main(void);
|
|||||||
yes)
|
yes)
|
||||||
SNMP_METHOD=agentx
|
SNMP_METHOD=agentx
|
||||||
;;
|
;;
|
||||||
smux|agentx)
|
agentx)
|
||||||
SNMP_METHOD="${enable_snmp}"
|
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
|
esac
|
||||||
AH_TEMPLATE([SNMP_SMUX], [Use SNMP SMUX to interface with snmpd])
|
|
||||||
AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX 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)
|
AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
|
||||||
fi
|
fi
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
WANT_LDP ?= 1
|
WANT_LDP ?= 1
|
||||||
WANT_PIM ?= 1
|
WANT_PIM ?= 1
|
||||||
WANT_OSPFAPI ?= 1
|
WANT_OSPFAPI ?= 1
|
||||||
WANT_TCP_ZEBRA ?= 0
|
|
||||||
WANT_BGP_VNC ?= 1
|
WANT_BGP_VNC ?= 1
|
||||||
WANT_CUMULUS_MODE ?= 0
|
WANT_CUMULUS_MODE ?= 0
|
||||||
WANT_MULTIPATH ?= 1
|
WANT_MULTIPATH ?= 1
|
||||||
@ -65,12 +64,6 @@ else
|
|||||||
USE_OSPFAPI=--enable-ospfapi=no
|
USE_OSPFAPI=--enable-ospfapi=no
|
||||||
endif
|
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)
|
ifeq ($(WANT_BGP_VNC), 1)
|
||||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||||
else
|
else
|
||||||
@ -123,7 +116,6 @@ override_dh_auto_configure:
|
|||||||
$(USE_OSPFAPI) \
|
$(USE_OSPFAPI) \
|
||||||
$(USE_MULTIPATH) \
|
$(USE_MULTIPATH) \
|
||||||
$(USE_LDP) \
|
$(USE_LDP) \
|
||||||
$(USE_TCP_ZEBRA) \
|
|
||||||
--enable-fpm \
|
--enable-fpm \
|
||||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||||
$(USE_FRR_VTY_GROUP) \
|
$(USE_FRR_VTY_GROUP) \
|
||||||
@ -162,12 +154,8 @@ override_dh_auto_install:
|
|||||||
mkdir -p debian/tmp/etc/frr/
|
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*
|
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
|
# leftover from previously shipping SMUX client OID 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
|
|
||||||
mkdir -p debian/tmp/usr/share/snmp/mibs
|
mkdir -p debian/tmp/usr/share/snmp/mibs
|
||||||
endif
|
|
||||||
|
|
||||||
# cleaning .la files
|
# cleaning .la files
|
||||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
WANT_LDP ?= 1
|
WANT_LDP ?= 1
|
||||||
WANT_PIM ?= 1
|
WANT_PIM ?= 1
|
||||||
WANT_OSPFAPI ?= 1
|
WANT_OSPFAPI ?= 1
|
||||||
WANT_TCP_ZEBRA ?= 0
|
|
||||||
WANT_BGP_VNC ?= 1
|
WANT_BGP_VNC ?= 1
|
||||||
WANT_CUMULUS_MODE ?= 0
|
WANT_CUMULUS_MODE ?= 0
|
||||||
WANT_MULTIPATH ?= 1
|
WANT_MULTIPATH ?= 1
|
||||||
@ -75,12 +74,6 @@ else
|
|||||||
USE_OSPFAPI=--enable-ospfapi=no
|
USE_OSPFAPI=--enable-ospfapi=no
|
||||||
endif
|
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)
|
ifeq ($(WANT_BGP_VNC), 1)
|
||||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||||
else
|
else
|
||||||
@ -152,7 +145,6 @@ override_dh_auto_configure:
|
|||||||
$(USE_OSPFAPI) \
|
$(USE_OSPFAPI) \
|
||||||
$(USE_MULTIPATH) \
|
$(USE_MULTIPATH) \
|
||||||
$(USE_LDP) \
|
$(USE_LDP) \
|
||||||
$(USE_TCP_ZEBRA) \
|
|
||||||
--enable-fpm \
|
--enable-fpm \
|
||||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||||
$(USE_FRR_VTY_GROUP) \
|
$(USE_FRR_VTY_GROUP) \
|
||||||
@ -196,12 +188,8 @@ override_dh_auto_install:
|
|||||||
mkdir -p debian/tmp/etc/frr/
|
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*
|
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
|
# leftover from previously shipping SMUX client OID 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
|
|
||||||
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
||||||
endif
|
|
||||||
|
|
||||||
# cleaning .la files
|
# cleaning .la files
|
||||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
WANT_LDP ?= 1
|
WANT_LDP ?= 1
|
||||||
WANT_PIM ?= 1
|
WANT_PIM ?= 1
|
||||||
WANT_OSPFAPI ?= 1
|
WANT_OSPFAPI ?= 1
|
||||||
WANT_TCP_ZEBRA ?= 0
|
|
||||||
WANT_BGP_VNC ?= 1
|
WANT_BGP_VNC ?= 1
|
||||||
WANT_CUMULUS_MODE ?= 0
|
WANT_CUMULUS_MODE ?= 0
|
||||||
WANT_MULTIPATH ?= 1
|
WANT_MULTIPATH ?= 1
|
||||||
@ -75,12 +74,6 @@ else
|
|||||||
USE_OSPFAPI=--enable-ospfapi=no
|
USE_OSPFAPI=--enable-ospfapi=no
|
||||||
endif
|
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)
|
ifeq ($(WANT_BGP_VNC), 1)
|
||||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||||
else
|
else
|
||||||
@ -152,7 +145,6 @@ override_dh_auto_configure:
|
|||||||
$(USE_OSPFAPI) \
|
$(USE_OSPFAPI) \
|
||||||
$(USE_MULTIPATH) \
|
$(USE_MULTIPATH) \
|
||||||
$(USE_LDP) \
|
$(USE_LDP) \
|
||||||
$(USE_TCP_ZEBRA) \
|
|
||||||
--enable-fpm \
|
--enable-fpm \
|
||||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||||
$(USE_FRR_VTY_GROUP) \
|
$(USE_FRR_VTY_GROUP) \
|
||||||
@ -194,12 +186,8 @@ override_dh_auto_install:
|
|||||||
mkdir -p debian/tmp/etc/frr/
|
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*
|
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
|
# leftover from previously shipping SMUX client OID 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
|
|
||||||
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
||||||
endif
|
|
||||||
|
|
||||||
# cleaning .la files
|
# cleaning .la files
|
||||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||||
|
@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \
|
|||||||
developer/index.rst \
|
developer/index.rst \
|
||||||
developer/ldpd-basic-test-setup.md \
|
developer/ldpd-basic-test-setup.md \
|
||||||
developer/library.rst \
|
developer/library.rst \
|
||||||
|
developer/logging.rst \
|
||||||
developer/Makefile.in \
|
developer/Makefile.in \
|
||||||
developer/maintainer-release-build.rst \
|
developer/maintainer-release-build.rst \
|
||||||
developer/memtypes.rst \
|
developer/memtypes.rst \
|
||||||
|
@ -7,6 +7,7 @@ Library Facilities (libfrr)
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
logging
|
||||||
memtypes
|
memtypes
|
||||||
hooks
|
hooks
|
||||||
cli
|
cli
|
||||||
|
131
doc/developer/logging.rst
Normal file
131
doc/developer/logging.rst
Normal 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
|
@ -102,14 +102,6 @@ Zebra Protocol Commands
|
|||||||
+-----------------------------------+-------+
|
+-----------------------------------+-------+
|
||||||
| ZEBRA_INTERFACE_DOWN | 6 |
|
| 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_ADD | 11 |
|
||||||
+-----------------------------------+-------+
|
+-----------------------------------+-------+
|
||||||
| ZEBRA_REDISTRIBUTE_DELETE | 12 |
|
| ZEBRA_REDISTRIBUTE_DELETE | 12 |
|
||||||
|
@ -126,7 +126,7 @@ These following options control the daemon's VTY (interactive command line) inte
|
|||||||
staticd 2616
|
staticd 2616
|
||||||
bfdd 2617
|
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
|
.. option:: --vty_socket vty-path
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
bfdd
|
||||||
bgpd
|
bgpd
|
||||||
eigrpd
|
eigrpd
|
||||||
isisd
|
isisd
|
||||||
|
@ -6,3 +6,50 @@ div.body {
|
|||||||
pre {
|
pre {
|
||||||
background-color: #e2e2e2;
|
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;
|
||||||
|
}
|
||||||
|
13
doc/user/_static/overrides.js
Normal file
13
doc/user/_static/overrides.js
Normal 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();
|
||||||
|
});
|
@ -179,7 +179,7 @@ The following commands are available inside the BGP configuration node.
|
|||||||
.. _bfd-ospf-peer-config:
|
.. _bfd-ospf-peer-config:
|
||||||
|
|
||||||
OSPF BFD Configuration
|
OSPF BFD Configuration
|
||||||
---------------------
|
----------------------
|
||||||
|
|
||||||
The following commands are available inside the interface configuration node.
|
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
|
Echo transmission interval: 50ms
|
||||||
|
|
||||||
frr# show bfd peer 192.168.0.1 json
|
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:
|
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
|
Zebra notifications: 4
|
||||||
|
|
||||||
frr# show bfd peer 192.168.0.1 counters json
|
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}
|
||||||
|
@ -1011,6 +1011,75 @@ is 4 octet long. The following format is used to define the community value.
|
|||||||
``internet``
|
``internet``
|
||||||
``internet`` represents well-known communities value 0.
|
``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``
|
||||||
``no-export`` represents well-known communities value ``NO_EXPORT``
|
``no-export`` represents well-known communities value ``NO_EXPORT``
|
||||||
``0xFFFFFF01``. All routes carry this value must not be advertised to
|
``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
|
it is considered as external BGP peer, so the route will not be announced to
|
||||||
the peer.
|
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
|
When the communities attribute is received duplicate community values in the
|
||||||
attribute are ignored and value is sorted in numerical order.
|
attribute are ignored and value is sorted in numerical order.
|
||||||
|
|
||||||
|
@ -358,6 +358,7 @@ def setup(app):
|
|||||||
app.add_object_type('clicmd', 'clicmd')
|
app.add_object_type('clicmd', 'clicmd')
|
||||||
# css overrides for HTML theme
|
# css overrides for HTML theme
|
||||||
app.add_stylesheet('overrides.css')
|
app.add_stylesheet('overrides.css')
|
||||||
|
app.add_javascript('overrides.js')
|
||||||
# load Pygments lexer for FRR config syntax
|
# load Pygments lexer for FRR config syntax
|
||||||
#
|
#
|
||||||
# NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we
|
# NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we
|
||||||
|
@ -5,12 +5,12 @@ Overview
|
|||||||
********
|
********
|
||||||
|
|
||||||
`FRR`_ is a routing software package that provides TCP/IP based routing
|
`FRR`_ is a routing software package that provides TCP/IP based routing
|
||||||
services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2,
|
services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more
|
||||||
OSPFv3, IS-IS, BGP-4, and BGP-4+ (:ref:`supported-rfcs`). FRR also supports
|
(see :ref:`supported-protocols`). FRR also supports
|
||||||
special BGP Route Reflector and Route Server behavior. In addition to
|
special BGP Route Reflector and Route Server behavior. In addition to
|
||||||
traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols.
|
traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols.
|
||||||
With SNMP daemon which supports SMUX and AgentX protocol, FRR provides routing
|
With an SNMP daemon that supports the AgentX protocol, FRR provides routing
|
||||||
protocol MIBs (:ref:`snmp-support`).
|
protocol MIB read-only access (:ref:`snmp-support`).
|
||||||
|
|
||||||
FRR uses an advanced software architecture to provide you with a high quality,
|
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
|
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:
|
||||||
|
|
||||||
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
|
.. role:: mark
|
||||||
- Babel
|
|
||||||
- EIGRP
|
|
||||||
- IS-IS
|
|
||||||
- LDP
|
|
||||||
- NHRP
|
|
||||||
- OSPFv2
|
|
||||||
- OSPFv3
|
|
||||||
- PIM
|
|
||||||
- RIP
|
|
||||||
- RIPNG
|
|
||||||
|
|
||||||
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:
|
.. _supported-rfcs:
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ SNMP Support
|
|||||||
:abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature
|
:abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature
|
||||||
for collecting network information from router and/or host. FRR itself does
|
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
|
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
|
a SNMP agent using the the AgentX protocol (:rfc:`2741`) and make the
|
||||||
(:rfc:`2741`) and make the routing protocol MIBs available through it.
|
routing protocol MIBs available through it.
|
||||||
|
|
||||||
Note that SNMP Support needs to be enabled at compile-time and loaded as module
|
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.
|
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
|
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
|
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/>`_
|
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
|
and as binary package for most Linux distributions.
|
||||||
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.
|
|
||||||
|
|
||||||
.. _agentx-configuration:
|
.. _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.
|
:file:`/etc/snmp/snmpd.conf`, the ``master agentx`` directive should be added.
|
||||||
In each of the FRR daemons, ``agentx`` command will enable AgentX support.
|
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
|
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:
|
Here is the syntax for using AgentX:
|
||||||
|
|
||||||
.. index:: agentx
|
.. index:: agentx
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "isisd/isis_constants.h"
|
#include "isisd/isis_constants.h"
|
||||||
#include "isisd/isis_circuit.h"
|
#include "isisd/isis_circuit.h"
|
||||||
#include "isisd/isis_network.h"
|
#include "isisd/isis_network.h"
|
||||||
|
#include "isisd/isis_pdu.h"
|
||||||
|
|
||||||
#include "privs.h"
|
#include "privs.h"
|
||||||
|
|
||||||
|
@ -536,7 +536,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
|
|||||||
*stream = stream_new(stream_size);
|
*stream = stream_new(stream_size);
|
||||||
} else {
|
} else {
|
||||||
if (STREAM_SIZE(*stream) != stream_size)
|
if (STREAM_SIZE(*stream) != stream_size)
|
||||||
stream_resize(*stream, stream_size);
|
stream_resize_inplace(stream, stream_size);
|
||||||
stream_reset(*stream);
|
stream_reset(*stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
lib/buffer.c
18
lib/buffer.c
@ -274,19 +274,12 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
|
|||||||
if (!b->head)
|
if (!b->head)
|
||||||
return BUFFER_EMPTY;
|
return BUFFER_EMPTY;
|
||||||
|
|
||||||
if (height < 1) {
|
if (height < 1)
|
||||||
zlog_warn(
|
|
||||||
"%s called with non-positive window height %d, forcing to 1",
|
|
||||||
__func__, height);
|
|
||||||
height = 1;
|
height = 1;
|
||||||
} else if (height >= 2)
|
else if (height >= 2)
|
||||||
height--;
|
height--;
|
||||||
if (width < 1) {
|
if (width < 1)
|
||||||
zlog_warn(
|
|
||||||
"%s called with non-positive window width %d, forcing to 1",
|
|
||||||
__func__, width);
|
|
||||||
width = 1;
|
width = 1;
|
||||||
}
|
|
||||||
|
|
||||||
/* For erase and more data add two to b's buffer_data count.*/
|
/* For erase and more data add two to b's buffer_data count.*/
|
||||||
if (b->head->next == NULL) {
|
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;
|
iov_alloc *= 2;
|
||||||
if (iov != small_iov) {
|
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 = XREALLOC(MTYPE_TMP, iov,
|
||||||
iov_alloc * sizeof(*iov));
|
iov_alloc * sizeof(*iov));
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
|
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
|
||||||
# define _RET_NONNULL , returns_nonnull
|
# define _RET_NONNULL , returns_nonnull
|
||||||
#endif
|
#endif
|
||||||
|
#if __has_attribute(fallthrough)
|
||||||
|
# define _FALLTHROUGH __attribute__((fallthrough));
|
||||||
|
#endif
|
||||||
# define _CONSTRUCTOR(x) constructor(x)
|
# define _CONSTRUCTOR(x) constructor(x)
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
@ -34,6 +37,9 @@
|
|||||||
# define _DESTRUCTOR(x) destructor(x)
|
# define _DESTRUCTOR(x) destructor(x)
|
||||||
# define _ALLOC_SIZE(x) alloc_size(x)
|
# define _ALLOC_SIZE(x) alloc_size(x)
|
||||||
#endif
|
#endif
|
||||||
|
#if __GNUC__ >= 7
|
||||||
|
# define _FALLTHROUGH __attribute__((fallthrough));
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
@ -55,6 +61,9 @@
|
|||||||
#ifndef _ALLOC_SIZE
|
#ifndef _ALLOC_SIZE
|
||||||
# define _ALLOC_SIZE(x)
|
# define _ALLOC_SIZE(x)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef _FALLTHROUGH
|
||||||
|
#define _FALLTHROUGH
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for warnings on macros, put in the macro content like this:
|
* for warnings on macros, put in the macro content like this:
|
||||||
|
@ -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)
|
void log_ref_display(struct vty *vty, uint32_t code, bool json)
|
||||||
{
|
{
|
||||||
struct log_ref *ref;
|
struct log_ref *ref;
|
||||||
struct json_object *top, *obj;
|
struct json_object *top = NULL, *obj = NULL;
|
||||||
struct list *errlist;
|
struct list *errlist;
|
||||||
struct listnode *ln;
|
struct listnode *ln;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
|
|||||||
char ubuf[256];
|
char ubuf[256];
|
||||||
|
|
||||||
snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
|
snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
|
||||||
code, ref->title);
|
ref->code, ref->title);
|
||||||
memset(ubuf, '=', strlen(pbuf));
|
memset(ubuf, '=', strlen(pbuf));
|
||||||
ubuf[sizeof(ubuf) - 1] = '\0';
|
ubuf[sizeof(ubuf) - 1] = '\0';
|
||||||
|
|
||||||
|
13
lib/if.c
13
lib/if.c
@ -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
|
* this should not be considered as an update
|
||||||
* then create the new interface
|
* 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);
|
return if_create(name, vrf_id);
|
||||||
/* If it came from the kernel
|
/* If it came from the kernel
|
||||||
* or by way of zclient, believe it and update
|
* 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);
|
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 ? */
|
/* Does this interface support broadcast ? */
|
||||||
int if_is_broadcast(struct interface *ifp)
|
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, "IEEE 802.15.4");
|
||||||
llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
|
llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
|
||||||
default:
|
default:
|
||||||
zlog_warn("Unknown value %d", llt);
|
flog_err(LIB_ERR_DEVELOPMENT, "Unknown value %d", llt);
|
||||||
return "Unknown type!";
|
return "Unknown type!";
|
||||||
#undef llts
|
#undef llts
|
||||||
}
|
}
|
||||||
|
1
lib/if.h
1
lib/if.h
@ -497,6 +497,7 @@ extern int if_is_operative(struct interface *);
|
|||||||
extern int if_is_no_ptm_operative(struct interface *);
|
extern int if_is_no_ptm_operative(struct interface *);
|
||||||
extern int if_is_loopback(struct interface *);
|
extern int if_is_loopback(struct interface *);
|
||||||
extern int if_is_vrf(struct interface *ifp);
|
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_broadcast(struct interface *);
|
||||||
extern int if_is_pointopoint(struct interface *);
|
extern int if_is_pointopoint(struct interface *);
|
||||||
extern int if_is_multicast(struct interface *);
|
extern int if_is_multicast(struct interface *);
|
||||||
|
@ -868,11 +868,16 @@ int zlog_rotate(void)
|
|||||||
save_errno = errno;
|
save_errno = errno;
|
||||||
umask(oldumask);
|
umask(oldumask);
|
||||||
if (zl->fp == NULL) {
|
if (zl->fp == NULL) {
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&loglock);
|
||||||
|
|
||||||
flog_err_sys(
|
flog_err_sys(
|
||||||
LIB_ERR_SYSTEM_CALL,
|
LIB_ERR_SYSTEM_CALL,
|
||||||
"Log rotate failed: cannot open file %s for append: %s",
|
"Log rotate failed: cannot open file %s for append: %s",
|
||||||
zl->filename, safe_strerror(save_errno));
|
zl->filename, safe_strerror(save_errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&loglock);
|
||||||
} else {
|
} else {
|
||||||
logfile_fd = fileno(zl->fp);
|
logfile_fd = fileno(zl->fp);
|
||||||
zl->maxlvl[ZLOG_DEST_FILE] = level;
|
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_ADD),
|
||||||
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
|
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
|
||||||
DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER),
|
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_ADD),
|
||||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE),
|
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE),
|
||||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
|
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
|
||||||
|
@ -87,7 +87,7 @@ extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
|
|||||||
|
|
||||||
/* For logs which have error codes associated with them */
|
/* For logs which have error codes associated with them */
|
||||||
#define flog_err(ferr_id, format, ...) \
|
#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, ...) \
|
#define flog_err_sys(ferr_id, format, ...) \
|
||||||
flog_err(ferr_id, format, ##__VA_ARGS__)
|
flog_err(ferr_id, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
1416
lib/smux.c
1416
lib/smux.c
File diff suppressed because it is too large
Load Diff
@ -580,31 +580,7 @@ int sockopt_tcp_rtt(int sock)
|
|||||||
|
|
||||||
int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
|
int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
|
#if HAVE_DECL_TCP_MD5SIG
|
||||||
/* 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
|
|
||||||
int ret;
|
int ret;
|
||||||
#ifndef GNU_LINUX
|
#ifndef GNU_LINUX
|
||||||
/*
|
/*
|
||||||
|
@ -143,7 +143,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread)
|
|||||||
|
|
||||||
long spf_backoff_schedule(struct spf_backoff *backoff)
|
long spf_backoff_schedule(struct spf_backoff *backoff)
|
||||||
{
|
{
|
||||||
long rv;
|
long rv = 0;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
@ -176,9 +176,6 @@ long spf_backoff_schedule(struct spf_backoff *backoff)
|
|||||||
else
|
else
|
||||||
rv = backoff->long_delay;
|
rv = backoff->long_delay;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
zlog_warn("SPF Back-off(%s) in unknown state", backoff->name);
|
|
||||||
rv = backoff->init_delay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backoff_debug(
|
backoff_debug(
|
||||||
|
41
lib/stream.c
41
lib/stream.c
@ -28,9 +28,9 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "lib_errors.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
|
DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
|
||||||
DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data")
|
|
||||||
DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
|
DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
|
||||||
|
|
||||||
/* Tests whether a position is valid */
|
/* Tests whether a position is valid */
|
||||||
@ -100,9 +100,7 @@ struct stream *stream_new(size_t size)
|
|||||||
|
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream));
|
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream) + size);
|
||||||
|
|
||||||
s->data = XMALLOC(MTYPE_STREAM_DATA, size);
|
|
||||||
|
|
||||||
s->getp = s->endp = 0;
|
s->getp = s->endp = 0;
|
||||||
s->next = NULL;
|
s->next = NULL;
|
||||||
@ -116,7 +114,6 @@ void stream_free(struct stream *s)
|
|||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XFREE(MTYPE_STREAM_DATA, s->data);
|
|
||||||
XFREE(MTYPE_STREAM, s);
|
XFREE(MTYPE_STREAM, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,27 +163,33 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2,
|
|||||||
return new;
|
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;
|
struct stream *orig = *sptr;
|
||||||
STREAM_VERIFY_SANE(s);
|
|
||||||
|
|
||||||
newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize);
|
STREAM_VERIFY_SANE(orig);
|
||||||
|
|
||||||
if (newdata == NULL)
|
orig = XREALLOC(MTYPE_STREAM, orig, sizeof(struct stream) + newsize);
|
||||||
return s->size;
|
|
||||||
|
|
||||||
s->data = newdata;
|
orig->size = newsize;
|
||||||
s->size = newsize;
|
|
||||||
|
|
||||||
if (s->endp > s->size)
|
if (orig->endp > orig->size)
|
||||||
s->endp = s->size;
|
orig->endp = orig->size;
|
||||||
if (s->getp > s->endp)
|
if (orig->getp > orig->endp)
|
||||||
s->getp = s->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)
|
size_t stream_get_getp(struct stream *s)
|
||||||
|
20
lib/stream.h
20
lib/stream.h
@ -98,14 +98,15 @@
|
|||||||
struct stream {
|
struct stream {
|
||||||
struct stream *next;
|
struct stream *next;
|
||||||
|
|
||||||
/* Remainder is ***private*** to stream
|
/*
|
||||||
|
* Remainder is ***private*** to stream
|
||||||
* direct access is frowned upon!
|
* direct access is frowned upon!
|
||||||
* Use the appropriate functions/macros
|
* Use the appropriate functions/macros
|
||||||
*/
|
*/
|
||||||
size_t getp; /* next get position */
|
size_t getp; /* next get position */
|
||||||
size_t endp; /* last valid data position */
|
size_t endp; /* last valid data position */
|
||||||
size_t size; /* size of data segment */
|
size_t size; /* size of data segment */
|
||||||
unsigned char *data; /* data pointer */
|
unsigned char data[0]; /* data pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* First in first out queue structure. */
|
/* First in first out queue structure. */
|
||||||
@ -154,7 +155,14 @@ extern struct stream *stream_new(size_t);
|
|||||||
extern void stream_free(struct stream *);
|
extern void stream_free(struct stream *);
|
||||||
extern struct stream *stream_copy(struct stream *, struct stream *src);
|
extern struct stream *stream_copy(struct stream *, struct stream *src);
|
||||||
extern struct stream *stream_dup(struct stream *);
|
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_getp(struct stream *);
|
||||||
extern size_t stream_get_endp(struct stream *);
|
extern size_t stream_get_endp(struct stream *);
|
||||||
extern size_t stream_get_size(struct stream *);
|
extern size_t stream_get_size(struct stream *);
|
||||||
|
@ -150,7 +150,6 @@ pkginclude_HEADERS += \
|
|||||||
lib/sha256.h \
|
lib/sha256.h \
|
||||||
lib/sigevent.h \
|
lib/sigevent.h \
|
||||||
lib/skiplist.h \
|
lib/skiplist.h \
|
||||||
lib/smux.h \
|
|
||||||
lib/sockopt.h \
|
lib/sockopt.h \
|
||||||
lib/sockunion.h \
|
lib/sockunion.h \
|
||||||
lib/spf_backoff.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_LIBADD = lib/libfrr.la $(SNMP_LIBS)
|
||||||
lib_libfrrsnmp_la_SOURCES = \
|
lib_libfrrsnmp_la_SOURCES = \
|
||||||
lib/agentx.c \
|
lib/agentx.c \
|
||||||
lib/smux.c \
|
|
||||||
lib/snmp.c \
|
lib/snmp.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock 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);
|
assert(node->lock > 0);
|
||||||
(*(unsigned *)&node->lock)--;
|
(*(unsigned *)&node->lock)--;
|
||||||
|
|
||||||
if (node->lock == 0) {
|
if (node->lock == 0)
|
||||||
route_node_delete(node);
|
route_node_delete(node);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
45
lib/thread.c
45
lib/thread.c
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
|
DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
|
||||||
DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master")
|
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")
|
DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -423,19 +424,11 @@ struct thread_master *thread_master_create(const char *name)
|
|||||||
/* Initialize I/O task data structures */
|
/* Initialize I/O task data structures */
|
||||||
getrlimit(RLIMIT_NOFILE, &limit);
|
getrlimit(RLIMIT_NOFILE, &limit);
|
||||||
rv->fd_limit = (int)limit.rlim_cur;
|
rv->fd_limit = (int)limit.rlim_cur;
|
||||||
rv->read =
|
rv->read = XCALLOC(MTYPE_THREAD_POLL,
|
||||||
XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
|
sizeof(struct thread *) * rv->fd_limit);
|
||||||
if (rv->read == NULL) {
|
|
||||||
XFREE(MTYPE_THREAD_MASTER, rv);
|
rv->write = XCALLOC(MTYPE_THREAD_POLL,
|
||||||
return NULL;
|
sizeof(struct thread *) * rv->fd_limit);
|
||||||
}
|
|
||||||
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->cpu_record = hash_create_size(
|
rv->cpu_record = hash_create_size(
|
||||||
8, (unsigned int (*)(void *))cpu_record_hash_key,
|
8, (unsigned int (*)(void *))cpu_record_hash_key,
|
||||||
@ -539,17 +532,23 @@ static struct thread *thread_trim_head(struct thread_list *list)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define THREAD_UNUSED_DEPTH 10
|
||||||
|
|
||||||
/* Move thread to unuse list. */
|
/* Move thread to unuse list. */
|
||||||
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
||||||
{
|
{
|
||||||
assert(m != NULL && thread != NULL);
|
assert(m != NULL && thread != NULL);
|
||||||
assert(thread->next == NULL);
|
assert(thread->next == NULL);
|
||||||
assert(thread->prev == NULL);
|
assert(thread->prev == NULL);
|
||||||
thread->ref = NULL;
|
|
||||||
|
|
||||||
thread->type = THREAD_UNUSED;
|
|
||||||
thread->hist->total_active--;
|
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. */
|
/* Free all unused thread. */
|
||||||
@ -580,7 +579,7 @@ static void thread_array_free(struct thread_master *m,
|
|||||||
m->alloc--;
|
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)
|
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)
|
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 =
|
struct cancel_req *cr =
|
||||||
XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
|
XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
|
||||||
cr->thread = thread;
|
cr->thread = thread;
|
||||||
listnode_add(thread->master->cancel_req, cr);
|
listnode_add(master->cancel_req, cr);
|
||||||
do_thread_cancel(thread->master);
|
do_thread_cancel(master);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&thread->master->mtx);
|
pthread_mutex_unlock(&master->mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
122
lib/vrf.c
122
lib/vrf.c
@ -342,91 +342,103 @@ void *vrf_info_lookup(vrf_id_t vrf_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VRF bit-map
|
* VRF hash for storing set or not.
|
||||||
*/
|
*/
|
||||||
|
struct vrf_bit_set {
|
||||||
#define VRF_BITMAP_NUM_OF_GROUPS 1024
|
vrf_id_t vrf_id;
|
||||||
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
|
bool set;
|
||||||
#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];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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)
|
vrf_bitmap_t vrf_bitmap_init(void)
|
||||||
{
|
{
|
||||||
return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
|
return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
|
||||||
sizeof(struct vrf_bitmap));
|
"VRF BIT HASH");
|
||||||
}
|
}
|
||||||
|
|
||||||
void vrf_bitmap_free(vrf_bitmap_t bmap)
|
void vrf_bitmap_free(vrf_bitmap_t bmap)
|
||||||
{
|
{
|
||||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
struct hash *vrf_hash = bmap;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (bmap == VRF_BITMAP_NULL)
|
if (vrf_hash == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
|
hash_clean(vrf_hash, vrf_hash_bitmap_free);
|
||||||
if (bm->groups[i])
|
hash_free(vrf_hash);
|
||||||
XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
|
|
||||||
|
|
||||||
XFREE(MTYPE_VRF_BITMAP, bm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
struct hash *vrf_hash = bmap;
|
||||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
struct vrf_bit_set *bit;
|
||||||
|
|
||||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bm->groups[group] == NULL)
|
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
||||||
bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
|
bit->set = true;
|
||||||
VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
|
|
||||||
|
|
||||||
SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
|
||||||
VRF_BITMAP_FLAG(offset));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
struct hash *vrf_hash = bmap;
|
||||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
struct vrf_bit_set *bit;
|
||||||
|
|
||||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||||
|| bm->groups[group] == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
||||||
VRF_BITMAP_FLAG(offset));
|
bit->set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
struct hash *vrf_hash = bmap;
|
||||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
struct vrf_bit_set *bit;
|
||||||
|
|
||||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||||
|| bm->groups[group] == NULL)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
bit = hash_lookup(vrf_hash, &lookup);
|
||||||
VRF_BITMAP_FLAG(offset))
|
if (bit)
|
||||||
? 1
|
return bit->set;
|
||||||
: 0;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vrf_autocomplete(vector comps, struct cmd_token *token)
|
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;
|
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')
|
if (!vrf || vrf->data.l.netns_name[0] == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
if (vrf->vrf_id == VRF_DEFAULT)
|
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)
|
if (fd < 0 || name == NULL)
|
||||||
return fd;
|
return fd;
|
||||||
if (vrf_is_mapped_on_netns(vrf_id))
|
if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id)))
|
||||||
return fd;
|
return fd;
|
||||||
#ifdef SO_BINDTODEVICE
|
#ifdef SO_BINDTODEVICE
|
||||||
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
|
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
|
||||||
|
@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void);
|
|||||||
#define VRF_DEFAULT vrf_get_default_id()
|
#define VRF_DEFAULT vrf_get_default_id()
|
||||||
|
|
||||||
/* VRF is mapped on netns or not ? */
|
/* 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 */
|
/* VRF switch from NETNS */
|
||||||
extern int vrf_switch_to_netns(vrf_id_t vrf_id);
|
extern int vrf_switch_to_netns(vrf_id_t vrf_id);
|
||||||
|
239
lib/zclient.c
239
lib/zclient.c
@ -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
|
* "xdr_encode"-like interface that allows daemon (client) to send
|
||||||
* a message to zebra server for a route that needs to be
|
* a message to zebra server for a route that needs to be
|
||||||
* added/deleted to the kernel. Info about the route is specified
|
* 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 info down the zclient socket using the stream_* functions.
|
||||||
*
|
*
|
||||||
* The corresponding read ("xdr_decode") function on the server
|
* 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
|
* 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
|
* is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole
|
||||||
* nexthop.
|
* nexthop.
|
||||||
*
|
*
|
||||||
* The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
|
* The original struct zapi_route_*() infrastructure was built around
|
||||||
* infrastructure was built around the traditional (32-bit "gate OR
|
* the traditional (32-bit "gate OR ifindex") nexthop data unit.
|
||||||
* ifindex") nexthop data unit. A special encoding can be used to feed
|
* A special encoding can be used to feed onlink (64-bit "gate AND ifindex")
|
||||||
* onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
|
* nexthops into zapi_route_encode() using the same zapi_route structure.
|
||||||
* using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
|
* This is done by setting zapi_route fields as follows:
|
||||||
* fields as follows:
|
|
||||||
* - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
|
* - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
|
||||||
* - .nexthop_num == .ifindex_num
|
* - .nexthop_num == .ifindex_num
|
||||||
* - .nexthop and .ifindex are filled with gate and ifindex parts of
|
* - .nexthop and .ifindex are filled with gate and ifindex parts of
|
||||||
* each compound nexthop, both in the same order
|
* 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
|
* If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
|
||||||
* byte value.
|
* byte value.
|
||||||
*
|
*
|
||||||
@ -734,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
|
|||||||
*
|
*
|
||||||
* XXX: No attention paid to alignment.
|
* 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,
|
int zclient_route_send(uint8_t cmd, struct zclient *zclient,
|
||||||
struct zapi_route *api)
|
struct zapi_route *api)
|
||||||
{
|
{
|
||||||
|
@ -73,10 +73,6 @@ typedef enum {
|
|||||||
ZEBRA_ROUTE_ADD,
|
ZEBRA_ROUTE_ADD,
|
||||||
ZEBRA_ROUTE_DELETE,
|
ZEBRA_ROUTE_DELETE,
|
||||||
ZEBRA_ROUTE_NOTIFY_OWNER,
|
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_ADD,
|
||||||
ZEBRA_REDISTRIBUTE_DELETE,
|
ZEBRA_REDISTRIBUTE_DELETE,
|
||||||
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
||||||
@ -286,7 +282,7 @@ struct zclient {
|
|||||||
*/
|
*/
|
||||||
#define ZAPI_MESSAGE_TABLEID 0x80
|
#define ZAPI_MESSAGE_TABLEID 0x80
|
||||||
|
|
||||||
#define ZSERV_VERSION 5
|
#define ZSERV_VERSION 6
|
||||||
/* Zserv protocol message header */
|
/* Zserv protocol message header */
|
||||||
struct zmsghdr {
|
struct zmsghdr {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
@ -353,37 +349,6 @@ struct zapi_route {
|
|||||||
uint32_t tableid;
|
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 {
|
struct zapi_pw {
|
||||||
char ifname[IF_NAMESIZE];
|
char ifname[IF_NAMESIZE];
|
||||||
ifindex_t ifindex;
|
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_interface_if_set_value(struct stream *, struct interface *);
|
||||||
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
|
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 struct interface *zebra_interface_link_params_read(struct stream *);
|
||||||
extern size_t zebra_interface_link_params_write(struct stream *,
|
extern size_t zebra_interface_link_params_write(struct stream *,
|
||||||
struct interface *);
|
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,
|
zebra_size_t length, vrf_id_t vrf_id,
|
||||||
struct zapi_pw_status *pw);
|
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_route_send(uint8_t, struct zclient *, struct zapi_route *);
|
||||||
extern int zclient_send_rnh(struct zclient *zclient, int command,
|
extern int zclient_send_rnh(struct zclient *zclient, int command,
|
||||||
struct prefix *p, bool exact_match,
|
struct prefix *p, bool exact_match,
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "ospfd/ospf_lsdb.h"
|
#include "ospfd/ospf_lsdb.h"
|
||||||
#include "ospfd/ospf_neighbor.h"
|
#include "ospfd/ospf_neighbor.h"
|
||||||
#include "ospfd/ospf_dump.h"
|
#include "ospfd/ospf_dump.h"
|
||||||
|
#include "ospfd/ospf_route.h"
|
||||||
#include "ospfd/ospf_zebra.h"
|
#include "ospfd/ospf_zebra.h"
|
||||||
#include "ospfd/ospf_api.h"
|
#include "ospfd/ospf_api.h"
|
||||||
|
|
||||||
|
@ -1425,19 +1425,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
|
|||||||
newlsa->length = htons(length);
|
newlsa->length = htons(length);
|
||||||
|
|
||||||
/* Create OSPF LSA. */
|
/* Create OSPF LSA. */
|
||||||
if ((new = ospf_lsa_new()) == NULL) {
|
new = ospf_lsa_new_and_data(length);
|
||||||
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->area = area;
|
new->area = area;
|
||||||
new->oi = oi;
|
new->oi = oi;
|
||||||
|
@ -73,26 +73,6 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
|
|||||||
p->prefixlen);
|
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. */
|
/* Add an External info for AS-external-LSA. */
|
||||||
struct external_info *ospf_external_info_new(uint8_t type,
|
struct external_info *ospf_external_info_new(uint8_t type,
|
||||||
unsigned short instance)
|
unsigned short instance)
|
||||||
|
@ -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,
|
extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
|
||||||
unsigned short,
|
unsigned short,
|
||||||
struct prefix_ipv4 *);
|
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_asbr_status_update(struct ospf *, uint8_t);
|
||||||
|
|
||||||
extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
|
extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
|
||||||
|
@ -288,6 +288,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
|
|||||||
struct prefix_ipv4 asbr, p;
|
struct prefix_ipv4 asbr, p;
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct ospf_route *new, * or ;
|
struct ospf_route *new, * or ;
|
||||||
|
char buf1[INET_ADDRSTRLEN];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(lsa);
|
assert(lsa);
|
||||||
@ -304,10 +305,14 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
|
|||||||
return 0;
|
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(
|
zlog_debug(
|
||||||
"Route[External]: Calculate AS-external-LSA to %s/%d",
|
"Route[External]: Calculate AS-external-LSA to %s/%d adv_router %s",
|
||||||
inet_ntoa(al->header.id), ip_masklen(al->mask));
|
inet_ntoa(al->header.id), ip_masklen(al->mask), buf1);
|
||||||
|
}
|
||||||
|
|
||||||
/* (1) If the cost specified by the LSA is LSInfinity, or if the
|
/* (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. */
|
LSA's LS age is equal to MaxAge, then examine the next LSA. */
|
||||||
if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) {
|
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 (!rn || (or = rn->info) == NULL) {
|
||||||
if (IS_DEBUG_OSPF(lsa, LSA))
|
if (IS_DEBUG_OSPF(lsa, LSA))
|
||||||
zlog_debug("Route[External]: Adding a new route %s/%d",
|
zlog_debug("Route[External]: Adding a new route %s/%d with paths %u",
|
||||||
inet_ntoa(p.prefix), p.prefixlen);
|
inet_ntoa(p.prefix), p.prefixlen,
|
||||||
|
listcount(asbr_route->paths));
|
||||||
|
|
||||||
ospf_route_add(ospf->new_external_route, &p, new, asbr_route);
|
ospf_route_add(ospf->new_external_route, &p, new, asbr_route);
|
||||||
|
|
||||||
|
@ -977,20 +977,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area,
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create an OSPF LSA instance. */
|
/* Now, create an OSPF LSA instance. */
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(length);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Segment Routing belongs only to default VRF */
|
/* Segment Routing belongs only to default VRF */
|
||||||
new->vrf_id = VRF_DEFAULT;
|
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);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create an OSPF LSA instance. */
|
/* Now, create an OSPF LSA instance. */
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(length);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Segment Routing belongs only to default VRF */
|
/* Segment Routing belongs only to default VRF */
|
||||||
new->vrf_id = VRF_DEFAULT;
|
new->vrf_id = VRF_DEFAULT;
|
||||||
|
@ -810,8 +810,7 @@ struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah)
|
|||||||
{
|
{
|
||||||
struct ospf_lsa *new;
|
struct ospf_lsa *new;
|
||||||
|
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(OSPF_LSA_HEADER_SIZE);
|
||||||
new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE);
|
|
||||||
memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE);
|
memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
|
@ -167,6 +167,16 @@ struct ospf_lsa *ospf_lsa_new()
|
|||||||
return 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. */
|
/* Duplicate OSPF LSA. */
|
||||||
struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *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. */
|
/* 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,
|
struct in_addr data, uint8_t type, uint8_t tos,
|
||||||
uint16_t cost)
|
uint16_t cost)
|
||||||
{
|
{
|
||||||
@ -415,11 +425,11 @@ static char link_info_set(struct stream *s, struct in_addr id,
|
|||||||
* more.
|
* more.
|
||||||
* we try accomodate those here.
|
* 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;
|
size_t ret = OSPF_MAX_LSA_SIZE;
|
||||||
|
|
||||||
/* Can we enlarge the stream still? */
|
/* 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
|
/* we futz the size here for simplicity, really we need
|
||||||
* to account
|
* to account
|
||||||
* for just:
|
* 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.
|
* 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);
|
s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == OSPF_MAX_LSA_SIZE) {
|
if (ret == OSPF_MAX_LSA_SIZE) {
|
||||||
zlog_warn(
|
zlog_warn(
|
||||||
"%s: Out of space in LSA stream, left %zd, size %zd",
|
"%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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TOS based routing is not supported. */
|
/* TOS based routing is not supported. */
|
||||||
stream_put_ipv4(s, id.s_addr); /* Link ID. */
|
stream_put_ipv4(*s, id.s_addr); /* Link ID. */
|
||||||
stream_put_ipv4(s, data.s_addr); /* Link Data. */
|
stream_put_ipv4(*s, data.s_addr); /* Link Data. */
|
||||||
stream_putc(s, type); /* Link Type. */
|
stream_putc(*s, type); /* Link Type. */
|
||||||
stream_putc(s, tos); /* TOS = 0. */
|
stream_putc(*s, tos); /* TOS = 0. */
|
||||||
stream_putw(s, cost); /* Link Cost. */
|
stream_putw(*s, cost); /* Link Cost. */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Describe Point-to-Point link (Section 12.4.1.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;
|
int links = 0;
|
||||||
struct ospf_neighbor *nbr;
|
struct ospf_neighbor *nbr;
|
||||||
@ -500,7 +511,7 @@ static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Describe Broadcast Link. */
|
/* 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 ospf_neighbor *dr;
|
||||||
struct in_addr id, mask;
|
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;
|
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. */
|
/* 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;
|
struct ospf_neighbor *nbr;
|
||||||
uint16_t cost = ospf_link_cost(oi);
|
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.*/
|
12.4.1.4.*/
|
||||||
/* from "edward rrr" <edward_rrr@hotmail.com>
|
/* from "edward rrr" <edward_rrr@hotmail.com>
|
||||||
http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
|
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;
|
int links = 0;
|
||||||
struct route_node *rn;
|
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. */
|
/* 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 listnode *node;
|
||||||
struct ospf_interface *oi;
|
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. */
|
/* 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;
|
unsigned long putp;
|
||||||
uint16_t cnt;
|
uint16_t cnt;
|
||||||
|
|
||||||
/* Set flags. */
|
/* Set flags. */
|
||||||
stream_putc(s, router_lsa_flags(area));
|
stream_putc(*s, router_lsa_flags(area));
|
||||||
|
|
||||||
/* Set Zero fields. */
|
/* Set Zero fields. */
|
||||||
stream_putc(s, 0);
|
stream_putc(*s, 0);
|
||||||
|
|
||||||
/* Keep pointer to # links. */
|
/* Keep pointer to # links. */
|
||||||
putp = stream_get_endp(s);
|
putp = stream_get_endp(*s);
|
||||||
|
|
||||||
/* Forward word */
|
/* Forward word */
|
||||||
stream_putw(s, 0);
|
stream_putw(*s, 0);
|
||||||
|
|
||||||
/* Set all link information. */
|
/* Set all link information. */
|
||||||
cnt = router_lsa_link_set(s, area);
|
cnt = router_lsa_link_set(s, area);
|
||||||
|
|
||||||
/* Set # of links here. */
|
/* 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)
|
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);
|
OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
|
||||||
|
|
||||||
/* Set router-LSA body fields. */
|
/* Set router-LSA body fields. */
|
||||||
ospf_router_lsa_body_set(s, area);
|
ospf_router_lsa_body_set(&s, area);
|
||||||
|
|
||||||
/* Set length. */
|
/* Set length. */
|
||||||
length = stream_get_endp(s);
|
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);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create OSPF LSA instance. */
|
/* Now, create OSPF LSA instance. */
|
||||||
if ((new = ospf_lsa_new()) == NULL) {
|
new = ospf_lsa_new_and_data(length);
|
||||||
zlog_err("%s: Unable to create new lsa", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
new->area = area;
|
new->area = area;
|
||||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||||
new->vrf_id = area->ospf->vrf_id;
|
new->vrf_id = area->ospf->vrf_id;
|
||||||
|
|
||||||
/* Copy LSA data to store, discard stream. */
|
/* Copy LSA data to store, discard stream. */
|
||||||
new->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(new->data, lsah, length);
|
memcpy(new->data, lsah, length);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
@ -997,17 +1005,13 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi)
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Create OSPF LSA instance. */
|
/* Create OSPF LSA instance. */
|
||||||
if ((new = ospf_lsa_new()) == NULL) {
|
new = ospf_lsa_new_and_data(length);
|
||||||
zlog_err("%s: ospf_lsa_new returned NULL", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
new->area = oi->area;
|
new->area = oi->area;
|
||||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||||
new->vrf_id = oi->ospf->vrf_id;
|
new->vrf_id = oi->ospf->vrf_id;
|
||||||
|
|
||||||
/* Copy LSA to store. */
|
/* Copy LSA to store. */
|
||||||
new->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(new->data, lsah, length);
|
memcpy(new->data, lsah, length);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
@ -1181,13 +1185,12 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area,
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Create OSPF LSA instance. */
|
/* Create OSPF LSA instance. */
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(length);
|
||||||
new->area = area;
|
new->area = area;
|
||||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||||
new->vrf_id = area->ospf->vrf_id;
|
new->vrf_id = area->ospf->vrf_id;
|
||||||
|
|
||||||
/* Copy LSA to store. */
|
/* Copy LSA to store. */
|
||||||
new->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(new->data, lsah, length);
|
memcpy(new->data, lsah, length);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
@ -1323,13 +1326,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area,
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Create OSPF LSA instance. */
|
/* Create OSPF LSA instance. */
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(length);
|
||||||
new->area = area;
|
new->area = area;
|
||||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||||
new->vrf_id = area->ospf->vrf_id;
|
new->vrf_id = area->ospf->vrf_id;
|
||||||
|
|
||||||
/* Copy LSA to store. */
|
/* Copy LSA to store. */
|
||||||
new->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(new->data, lsah, length);
|
memcpy(new->data, lsah, length);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
@ -1629,14 +1631,13 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create OSPF LSA instance. */
|
/* Now, create OSPF LSA instance. */
|
||||||
new = ospf_lsa_new();
|
new = ospf_lsa_new_and_data(length);
|
||||||
new->area = NULL;
|
new->area = NULL;
|
||||||
SET_FLAG(new->flags,
|
SET_FLAG(new->flags,
|
||||||
OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
|
OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
|
||||||
new->vrf_id = ospf->vrf_id;
|
new->vrf_id = ospf->vrf_id;
|
||||||
|
|
||||||
/* Copy LSA data to store, discard stream. */
|
/* Copy LSA data to store, discard stream. */
|
||||||
new->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(new->data, lsah, length);
|
memcpy(new->data, lsah, length);
|
||||||
stream_free(s);
|
stream_free(s);
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ extern int ospf_check_nbr_status(struct ospf *);
|
|||||||
|
|
||||||
/* Prototype for LSA primitive. */
|
/* Prototype for LSA primitive. */
|
||||||
extern struct ospf_lsa *ospf_lsa_new(void);
|
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 struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *);
|
||||||
extern void ospf_lsa_free(struct ospf_lsa *);
|
extern void ospf_lsa_free(struct ospf_lsa *);
|
||||||
extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);
|
extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "ospfd/ospf_lsdb.h"
|
#include "ospfd/ospf_lsdb.h"
|
||||||
#include "ospfd/ospf_neighbor.h"
|
#include "ospfd/ospf_neighbor.h"
|
||||||
#include "ospfd/ospf_dump.h"
|
#include "ospfd/ospf_dump.h"
|
||||||
|
#include "ospfd/ospf_route.h"
|
||||||
#include "ospfd/ospf_zebra.h"
|
#include "ospfd/ospf_zebra.h"
|
||||||
#include "ospfd/ospf_vty.h"
|
#include "ospfd/ospf_vty.h"
|
||||||
#include "ospfd/ospf_bfd.h"
|
#include "ospfd/ospf_bfd.h"
|
||||||
|
@ -1742,7 +1742,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create OSPF LSA instance. */
|
/* Create OSPF LSA instance. */
|
||||||
lsa = ospf_lsa_new();
|
lsa = ospf_lsa_new_and_data(length);
|
||||||
|
|
||||||
lsa->vrf_id = oi->ospf->vrf_id;
|
lsa->vrf_id = oi->ospf->vrf_id;
|
||||||
/* We may wish to put some error checking if type NSSA comes in
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsa->data = ospf_lsa_data_new(length);
|
|
||||||
memcpy(lsa->data, lsah, length);
|
memcpy(lsa->data, lsah, length);
|
||||||
|
|
||||||
if (IS_DEBUG_OSPF_EVENT)
|
if (IS_DEBUG_OSPF_EVENT)
|
||||||
|
@ -775,18 +775,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create an OSPF LSA instance. */
|
/* Now, create an OSPF LSA instance. */
|
||||||
if ((new = ospf_lsa_new()) == NULL) {
|
new = ospf_lsa_new_and_data(length);
|
||||||
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->area = OspfRI.area; /* Area must be null if the Opaque type is AS
|
new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
|
||||||
scope, fulfill otherwise */
|
scope, fulfill otherwise */
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "ospfd/ospf_flood.h"
|
#include "ospfd/ospf_flood.h"
|
||||||
#include "ospfd/ospf_ism.h"
|
#include "ospfd/ospf_ism.h"
|
||||||
#include "ospfd/ospf_dump.h"
|
#include "ospfd/ospf_dump.h"
|
||||||
|
#include "ospfd/ospf_route.h"
|
||||||
#include "ospfd/ospf_zebra.h"
|
#include "ospfd/ospf_zebra.h"
|
||||||
|
|
||||||
/* OSPF2-MIB. */
|
/* OSPF2-MIB. */
|
||||||
|
@ -1201,18 +1201,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
|
|||||||
lsah->length = htons(length);
|
lsah->length = htons(length);
|
||||||
|
|
||||||
/* Now, create an OSPF LSA instance. */
|
/* Now, create an OSPF LSA instance. */
|
||||||
if ((new = ospf_lsa_new()) == NULL) {
|
new = ospf_lsa_new_and_data(length);
|
||||||
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->vrf_id = ospf->vrf_id;
|
new->vrf_id = ospf->vrf_id;
|
||||||
if (area && area->ospf)
|
if (area && area->ospf)
|
||||||
|
@ -111,10 +111,11 @@ static int ospf_interface_add(int command, struct zclient *zclient,
|
|||||||
|
|
||||||
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
|
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
|
||||||
zlog_debug(
|
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->name, ospf_vrf_id_to_name(ifp->vrf_id),
|
||||||
ifp->vrf_id, ifp->ifindex,
|
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);
|
assert(ifp->info);
|
||||||
|
|
||||||
@ -128,6 +129,8 @@ static int ospf_interface_add(int command, struct zclient *zclient,
|
|||||||
if (!ospf)
|
if (!ospf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
ospf_if_recalculate_output_cost(ifp);
|
||||||
|
|
||||||
ospf_if_update(ospf, ifp);
|
ospf_if_update(ospf, ifp);
|
||||||
|
|
||||||
hook_call(ospf_if_update, ifp);
|
hook_call(ospf_if_update, ifp);
|
||||||
@ -448,14 +451,17 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
|
|||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
|
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(
|
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])),
|
prefix2str(p, buf[0], sizeof(buf[0])),
|
||||||
inet_ntop(AF_INET, &path->nexthop,
|
inet_ntop(AF_INET, &path->nexthop,
|
||||||
buf[1], sizeof(buf[1])),
|
buf[1], sizeof(buf[1])),
|
||||||
path->ifindex);
|
path->ifindex, ifp ? ifp->name : " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api.nexthop_num = count;
|
api.nexthop_num = count;
|
||||||
|
@ -52,10 +52,10 @@
|
|||||||
#include "ospfd/ospf_spf.h"
|
#include "ospfd/ospf_spf.h"
|
||||||
#include "ospfd/ospf_packet.h"
|
#include "ospfd/ospf_packet.h"
|
||||||
#include "ospfd/ospf_dump.h"
|
#include "ospfd/ospf_dump.h"
|
||||||
|
#include "ospfd/ospf_route.h"
|
||||||
#include "ospfd/ospf_zebra.h"
|
#include "ospfd/ospf_zebra.h"
|
||||||
#include "ospfd/ospf_abr.h"
|
#include "ospfd/ospf_abr.h"
|
||||||
#include "ospfd/ospf_flood.h"
|
#include "ospfd/ospf_flood.h"
|
||||||
#include "ospfd/ospf_route.h"
|
|
||||||
#include "ospfd/ospf_ase.h"
|
#include "ospfd/ospf_ase.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
|
|||||||
char addr_str[INET_ADDRSTRLEN];
|
char addr_str[INET_ADDRSTRLEN];
|
||||||
struct pim_assert_metric *am;
|
struct pim_assert_metric *am;
|
||||||
struct in_addr ifaddr;
|
struct in_addr ifaddr;
|
||||||
char pref_str[5];
|
char pref_str[16];
|
||||||
char metr_str[7];
|
char metr_str[16];
|
||||||
|
|
||||||
ifaddr = pim_ifp->primary_address;
|
ifaddr = pim_ifp->primary_address;
|
||||||
|
|
||||||
|
@ -1495,14 +1495,6 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
|
|||||||
return 0;
|
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)
|
bool pim_if_is_vrf_device(struct interface *ifp)
|
||||||
{
|
{
|
||||||
if (if_is_vrf(ifp))
|
if (if_is_vrf(ifp))
|
||||||
|
@ -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_if_connected_to_source(struct interface *ifp, struct in_addr src);
|
||||||
int pim_update_source_set(struct interface *ifp, struct in_addr source);
|
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);
|
bool pim_if_is_vrf_device(struct interface *ifp);
|
||||||
|
|
||||||
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
|
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
|
||||||
|
@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
|||||||
ifchannel list is empty before deleting upstream_del
|
ifchannel list is empty before deleting upstream_del
|
||||||
ref count will take care of it.
|
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;
|
ch->upstream = NULL;
|
||||||
|
|
||||||
THREAD_OFF(ch->t_ifjoin_expiry_timer);
|
THREAD_OFF(ch->t_ifjoin_expiry_timer);
|
||||||
|
@ -37,19 +37,20 @@
|
|||||||
|
|
||||||
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
|
char *out;
|
||||||
struct prefix_sg sg;
|
struct prefix_sg sg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sg.src = c_oil->oil.mfcc_origin;
|
sg.src = c_oil->oil.mfcc_origin;
|
||||||
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
||||||
sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
|
snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
|
||||||
c_oil->oil.mfcc_parent);
|
c_oil->oil.mfcc_parent);
|
||||||
|
|
||||||
|
out = buf + strlen(buf);
|
||||||
for (i = 0; i < MAXVIFS; i++) {
|
for (i = 0; i < MAXVIFS; i++) {
|
||||||
if (c_oil->oil.mfcc_ttls[i] != 0) {
|
if (c_oil->oil.mfcc_ttls[i] != 0) {
|
||||||
char buf1[10];
|
snprintf(out, buf + size - out, "%d ", i);
|
||||||
sprintf(buf1, "%d ", i);
|
out += strlen(out);
|
||||||
strcat(buf, buf1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +655,7 @@ static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
|
|||||||
{
|
{
|
||||||
struct pim_interface *pim_ifp = ifp->info;
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
|
|
||||||
if (pim_if_is_loopback(ifp))
|
if (if_is_loopback_or_vrf(ifp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (hello_send(ifp, holdtime)) {
|
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
|
* 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;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
|
|||||||
up->ref_count, up->flags,
|
up->ref_count, up->flags,
|
||||||
up->channel_oil->oil_ref_count);
|
up->channel_oil->oil_ref_count);
|
||||||
|
|
||||||
|
assert(up->ref_count > 0);
|
||||||
|
|
||||||
--up->ref_count;
|
--up->ref_count;
|
||||||
|
|
||||||
if (up->ref_count >= 1)
|
if (up->ref_count >= 1)
|
||||||
|
@ -31,7 +31,7 @@ Commands defined by this snap
|
|||||||
- `frr.readme`:
|
- `frr.readme`:
|
||||||
Returns this document `cat README_usage.md`
|
Returns this document `cat README_usage.md`
|
||||||
- `frr.set`:
|
- `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
|
and for debugging defined at this time (May get removed later - do not
|
||||||
depend on them). These are mainly intended to debug the Snap
|
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
|
These settings require either a reboot or a manual configuration with
|
||||||
`sysctl` as well.
|
`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}
|
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
|
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`
|
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
|
for the next restart of zebra. Please reboot or restart zebra after
|
||||||
changing the mode to become effective.
|
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
|
FAQ
|
||||||
---
|
---
|
||||||
- frr.vtysh displays `--MORE--` on long output. How to suppress this?
|
- frr.vtysh displays `--MORE--` on long output. How to suppress this?
|
||||||
|
@ -5,9 +5,16 @@ set -e -x
|
|||||||
if ! [ -e $SNAP_DATA/bgpd.conf ]; then
|
if ! [ -e $SNAP_DATA/bgpd.conf ]; then
|
||||||
cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
|
cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
|
||||||
fi
|
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 \
|
exec $SNAP/sbin/bgpd \
|
||||||
-f $SNAP_DATA/bgpd.conf \
|
-f $SNAP_DATA/bgpd.conf \
|
||||||
--pid_file $SNAP_DATA/bgpd.pid \
|
--pid_file $SNAP_DATA/bgpd.pid \
|
||||||
--socket $SNAP_DATA/zsock \
|
--socket $SNAP_DATA/zsock \
|
||||||
--vty_socket $SNAP_DATA
|
--vty_socket $SNAP_DATA \
|
||||||
|
--moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS
|
||||||
|
|
||||||
|
@ -28,11 +28,34 @@ case $1 in
|
|||||||
;;
|
;;
|
||||||
esac
|
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 "Usage:"
|
||||||
echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
|
echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
|
||||||
|
echo " ${SNAP_NAME}.set rpki {disable|enable}"
|
||||||
echo ""
|
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
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -136,7 +136,7 @@ apps:
|
|||||||
- network-bind
|
- network-bind
|
||||||
- network-control
|
- network-control
|
||||||
bgpd-debug:
|
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:
|
plugs:
|
||||||
- network
|
- network
|
||||||
- network-bind
|
- network-bind
|
||||||
@ -221,8 +221,27 @@ apps:
|
|||||||
- network-control
|
- network-control
|
||||||
|
|
||||||
parts:
|
parts:
|
||||||
frr:
|
rtrlib:
|
||||||
build-packages:
|
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:
|
||||||
|
after: [rtrlib]
|
||||||
|
build-packages:
|
||||||
|
- gcc
|
||||||
- autoconf
|
- autoconf
|
||||||
- automake
|
- automake
|
||||||
- libtool
|
- libtool
|
||||||
@ -247,6 +266,7 @@ parts:
|
|||||||
- flex
|
- flex
|
||||||
- python3-dev
|
- python3-dev
|
||||||
- protobuf-c-compiler
|
- protobuf-c-compiler
|
||||||
|
- python3-sphinx
|
||||||
stage-packages:
|
stage-packages:
|
||||||
- coreutils
|
- coreutils
|
||||||
- iproute2
|
- iproute2
|
||||||
@ -276,6 +296,7 @@ parts:
|
|||||||
- --enable-ldpd
|
- --enable-ldpd
|
||||||
- --enable-fpm
|
- --enable-fpm
|
||||||
- --enable-protobuf
|
- --enable-protobuf
|
||||||
|
- --enable-rpki
|
||||||
- --enable-configfile-mask=0640
|
- --enable-configfile-mask=0640
|
||||||
- --enable-logfile-mask=0640
|
- --enable-logfile-mask=0640
|
||||||
- --localstatedir=/var/run
|
- --localstatedir=/var/run
|
||||||
|
@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole,
|
|||||||
"Table to configure\n"
|
"Table to configure\n"
|
||||||
"The table number 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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf,
|
|||||||
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
||||||
struct static_vrf *svrf = vrf->info;
|
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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface,
|
|||||||
return CMD_WARNING_CONFIG_FAILED;
|
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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf,
|
|||||||
struct static_vrf *svrf = vrf->info;
|
struct static_vrf *svrf = vrf->info;
|
||||||
struct static_vrf *nh_svrf;
|
struct static_vrf *nh_svrf;
|
||||||
|
|
||||||
if (table_str && !vrf_is_backend_netns()) {
|
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -984,7 +984,7 @@ DEFPY(ip_route,
|
|||||||
struct static_vrf *nh_svrf;
|
struct static_vrf *nh_svrf;
|
||||||
const char *flag = NULL;
|
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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf,
|
|||||||
struct static_vrf *nh_svrf;
|
struct static_vrf *nh_svrf;
|
||||||
const char *flag = NULL;
|
const char *flag = NULL;
|
||||||
|
|
||||||
if (table_str && !vrf_is_backend_netns()) {
|
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole,
|
|||||||
"Table to configure\n"
|
"Table to configure\n"
|
||||||
"The table number 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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf,
|
|||||||
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
||||||
struct static_vrf *svrf = vrf->info;
|
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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface,
|
|||||||
struct static_vrf *svrf;
|
struct static_vrf *svrf;
|
||||||
struct static_vrf *nh_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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf,
|
|||||||
struct static_vrf *svrf = vrf->info;
|
struct static_vrf *svrf = vrf->info;
|
||||||
struct static_vrf *nh_svrf;
|
struct static_vrf *nh_svrf;
|
||||||
|
|
||||||
if (table_str && !vrf_is_backend_netns()) {
|
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1309,7 +1309,7 @@ DEFPY(ipv6_route,
|
|||||||
struct static_vrf *svrf;
|
struct static_vrf *svrf;
|
||||||
struct static_vrf *nh_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,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf,
|
|||||||
struct static_vrf *svrf = vrf->info;
|
struct static_vrf *svrf = vrf->info;
|
||||||
struct static_vrf *nh_svrf;
|
struct static_vrf *nh_svrf;
|
||||||
|
|
||||||
if (table_str && !vrf_is_backend_netns()) {
|
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"%% table param only available when running on netns-based vrfs\n");
|
"%% table param only available when running on netns-based vrfs\n");
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "nexthop.h"
|
#include "nexthop.h"
|
||||||
#include "nexthop_group.h"
|
#include "nexthop_group.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
#include "static_vrf.h"
|
#include "static_vrf.h"
|
||||||
#include "static_routes.h"
|
#include "static_routes.h"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
|
|
||||||
/* Zebra structure to hold current status. */
|
/* Zebra structure to hold current status. */
|
||||||
struct zclient *zclient;
|
struct zclient *zclient;
|
||||||
|
static struct hash *static_nht_hash;
|
||||||
|
|
||||||
static struct interface *zebra_interface_if_lookup(struct stream *s)
|
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);
|
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,
|
static int static_zebra_nexthop_update(int command, struct zclient *zclient,
|
||||||
zebra_size_t length, vrf_id_t vrf_id)
|
zebra_size_t length, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
|
struct static_nht_data *nhtd, lookup;
|
||||||
struct zapi_route nhr;
|
struct zapi_route nhr;
|
||||||
afi_t afi = AFI_IP;
|
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)
|
if (nhr.prefix.family == AF_INET6)
|
||||||
afi = AFI_IP6;
|
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);
|
static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
|
|||||||
mpls_enabled = cap->mpls_enabled;
|
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)
|
void static_zebra_nht_register(struct static_route *si, bool reg)
|
||||||
{
|
{
|
||||||
|
struct static_nht_data *nhtd, lookup;
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
|
afi_t afi = AFI_IP;
|
||||||
|
|
||||||
cmd = (reg) ?
|
cmd = (reg) ?
|
||||||
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
|
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.family = AF_INET;
|
||||||
p.prefixlen = IPV4_MAX_BITLEN;
|
p.prefixlen = IPV4_MAX_BITLEN;
|
||||||
p.u.prefix4 = si->addr.ipv4;
|
p.u.prefix4 = si->addr.ipv4;
|
||||||
|
afi = AFI_IP;
|
||||||
break;
|
break;
|
||||||
case STATIC_IPV6_GATEWAY:
|
case STATIC_IPV6_GATEWAY:
|
||||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||||
p.family = AF_INET6;
|
p.family = AF_INET6;
|
||||||
p.prefixlen = IPV6_MAX_BITLEN;
|
p.prefixlen = IPV6_MAX_BITLEN;
|
||||||
p.u.prefix6 = si->addr.ipv6;
|
p.u.prefix6 = si->addr.ipv6;
|
||||||
|
afi = AFI_IP6;
|
||||||
break;
|
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)
|
if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
|
||||||
zlog_warn("%s: Failure to send nexthop to zebra",
|
zlog_warn("%s: Failure to send nexthop to zebra",
|
||||||
__PRETTY_FUNCTION__);
|
__PRETTY_FUNCTION__);
|
||||||
|
|
||||||
si->nh_registered = reg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void static_zebra_route_add(struct route_node *rn,
|
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);
|
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
||||||
api.tag = si_changed->tag;
|
api.tag = si_changed->tag;
|
||||||
}
|
}
|
||||||
api.tableid = si_changed->table_id;
|
if (si_changed->table_id != 0) {
|
||||||
|
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
|
||||||
zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
|
api.tableid = si_changed->table_id;
|
||||||
|
}
|
||||||
for (/*loaded above*/; si; si = si->next) {
|
for (/*loaded above*/; si; si = si->next) {
|
||||||
api_nh = &api.nexthops[nh_num];
|
api_nh = &api.nexthops[nh_num];
|
||||||
if (si->nh_vrf_id == VRF_UNKNOWN)
|
if (si->nh_vrf_id == VRF_UNKNOWN)
|
||||||
@ -372,4 +457,8 @@ void static_zebra_init(void)
|
|||||||
zclient->interface_address_delete = interface_address_delete;
|
zclient->interface_address_delete = interface_address_delete;
|
||||||
zclient->route_notify_owner = route_notify_owner;
|
zclient->route_notify_owner = route_notify_owner;
|
||||||
zclient->nexthop_update = static_zebra_nexthop_update;
|
zclient->nexthop_update = static_zebra_nexthop_update;
|
||||||
|
|
||||||
|
static_nht_hash = hash_create(static_nht_hash_key,
|
||||||
|
static_nht_hash_cmp,
|
||||||
|
"Static Nexthop Tracking hash");
|
||||||
}
|
}
|
||||||
|
@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case CAPABILITY:
|
case CAPABILITY:
|
||||||
len += 2; /* to cover the OPT-Param header */
|
len += 2; /* to cover the OPT-Param header */
|
||||||
__attribute__ ((fallthrough));
|
_FALLTHROUGH
|
||||||
case OPT_PARAM:
|
case OPT_PARAM:
|
||||||
printf("len: %u\n", len);
|
printf("len: %u\n", len);
|
||||||
/* peek_for_as4 wants getp at capibility*/
|
/* peek_for_as4 wants getp at capibility*/
|
||||||
|
@ -57,7 +57,7 @@ int main(void)
|
|||||||
|
|
||||||
print_stream(s);
|
print_stream(s);
|
||||||
|
|
||||||
stream_resize(s, stream_get_endp(s));
|
stream_resize_inplace(&s, stream_get_endp(s));
|
||||||
|
|
||||||
print_stream(s);
|
print_stream(s);
|
||||||
|
|
||||||
|
@ -1435,24 +1435,6 @@ DEFUNSH(VTYSH_BGPD,
|
|||||||
return CMD_SUCCESS;
|
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
|
#endif
|
||||||
|
|
||||||
DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
|
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 VTY_NODE:
|
||||||
case KEYCHAIN_NODE:
|
case KEYCHAIN_NODE:
|
||||||
case BFD_NODE:
|
case BFD_NODE:
|
||||||
|
case RPKI_NODE:
|
||||||
vtysh_execute("end");
|
vtysh_execute("end");
|
||||||
vtysh_execute("configure terminal");
|
vtysh_execute("configure terminal");
|
||||||
vty->node = CONFIG_NODE;
|
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_VNC_L2_GROUP_NODE)
|
||||||
vty->node = BGP_NODE;
|
vty->node = BGP_NODE;
|
||||||
return CMD_SUCCESS;
|
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",
|
DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
|
||||||
"Exit from VRF configuration mode\n")
|
"Exit from VRF configuration mode\n")
|
||||||
{
|
{
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "zebra/interface.h"
|
#include "zebra/interface.h"
|
||||||
#include "zebra/rib.h"
|
#include "zebra/rib.h"
|
||||||
|
#include "zebra/rt.h"
|
||||||
|
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
|
@ -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,
|
int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
|
||||||
const void *data, unsigned int alen)
|
const void *data, unsigned int alen)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
|
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
|
||||||
struct rtattr *rta, int len);
|
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,
|
extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
|
||||||
const void *data, unsigned int alen);
|
const void *data, unsigned int alen);
|
||||||
extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
|
extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
|
||||||
|
@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
|
|||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zebra_import_table_rm_update()
|
void zebra_import_table_rm_update(const char *rmap)
|
||||||
{
|
{
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
int i;
|
int i;
|
||||||
@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rmap_name = zebra_get_import_table_route_map(afi, i);
|
rmap_name = zebra_get_import_table_route_map(afi, i);
|
||||||
if (!rmap_name)
|
if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
table = zebra_vrf_other_route_table(afi, i,
|
table = zebra_vrf_other_route_table(afi, i,
|
||||||
VRF_DEFAULT);
|
VRF_DEFAULT);
|
||||||
for (rn = route_top(table); rn; rn = route_next(rn)) {
|
for (rn = route_top(table); rn; rn = route_next(rn)) {
|
||||||
|
@ -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 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 */
|
#endif /* _ZEBRA_REDISTRIBUTE_H */
|
||||||
|
@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
|
|||||||
vrf_id_t vrf_id);
|
vrf_id_t vrf_id);
|
||||||
|
|
||||||
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
|
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_route(void);
|
||||||
extern void rib_sweep_table(struct route_table *table);
|
extern void rib_sweep_table(struct route_table *table);
|
||||||
extern void rib_close_table(struct route_table *table);
|
extern void rib_close_table(struct route_table *table);
|
||||||
|
@ -246,6 +246,33 @@ static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
|
|||||||
return VRF_DEFAULT;
|
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. */
|
/* Looking up routing table by netlink interface. */
|
||||||
static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||||
int startup)
|
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 */
|
void *src = NULL; /* IPv6 srcdest source prefix */
|
||||||
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
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);
|
rtm = NLMSG_DATA(h);
|
||||||
|
|
||||||
if (startup && h->nlmsg_type != RTM_NEWROUTE)
|
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;
|
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,
|
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
|
||||||
&src_p, &nh, table, metric, mtu, distance, tag);
|
&src_p, &nh, table, metric, mtu, distance, tag);
|
||||||
} else {
|
} else {
|
||||||
@ -532,6 +574,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
|||||||
re->tag = tag;
|
re->tag = tag;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
struct nexthop *nh = NULL;
|
||||||
vrf_id_t nh_vrf_id;
|
vrf_id_t nh_vrf_id;
|
||||||
if (len < (int)sizeof(*rtnh)
|
if (len < (int)sizeof(*rtnh)
|
||||||
|| rtnh->rtnh_len > len)
|
|| 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])
|
if (tb[RTA_GATEWAY])
|
||||||
gate = RTA_DATA(
|
gate = RTA_DATA(
|
||||||
tb[RTA_GATEWAY]);
|
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 (gate) {
|
||||||
if (rtm->rtm_family == AF_INET) {
|
if (rtm->rtm_family == AF_INET) {
|
||||||
if (index)
|
if (index)
|
||||||
route_entry_nexthop_ipv4_ifindex_add(
|
nh = route_entry_nexthop_ipv4_ifindex_add(
|
||||||
re, gate,
|
re, gate,
|
||||||
prefsrc, index,
|
prefsrc, index,
|
||||||
nh_vrf_id);
|
nh_vrf_id);
|
||||||
else
|
else
|
||||||
route_entry_nexthop_ipv4_add(
|
nh = route_entry_nexthop_ipv4_add(
|
||||||
re, gate,
|
re, gate,
|
||||||
prefsrc,
|
prefsrc,
|
||||||
nh_vrf_id);
|
nh_vrf_id);
|
||||||
} else if (rtm->rtm_family
|
} else if (rtm->rtm_family
|
||||||
== AF_INET6) {
|
== AF_INET6) {
|
||||||
if (index)
|
if (index)
|
||||||
route_entry_nexthop_ipv6_ifindex_add(
|
nh = route_entry_nexthop_ipv6_ifindex_add(
|
||||||
re, gate, index,
|
re, gate, index,
|
||||||
nh_vrf_id);
|
nh_vrf_id);
|
||||||
else
|
else
|
||||||
route_entry_nexthop_ipv6_add(
|
nh = route_entry_nexthop_ipv6_add(
|
||||||
re, gate,
|
re, gate,
|
||||||
nh_vrf_id);
|
nh_vrf_id);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
route_entry_nexthop_ifindex_add(
|
nh = route_entry_nexthop_ifindex_add(
|
||||||
re, index, nh_vrf_id);
|
re, index, nh_vrf_id);
|
||||||
|
|
||||||
|
if (nh && num_labels)
|
||||||
|
nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
|
||||||
|
num_labels, labels);
|
||||||
|
|
||||||
if (rtnh->rtnh_len == 0)
|
if (rtnh->rtnh_len == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -141,13 +141,3 @@ if DEV_BUILD
|
|||||||
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
|
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
|
||||||
endif
|
endif
|
||||||
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
|
|
||||||
|
622
zebra/zapi_msg.c
622
zebra/zapi_msg.c
@ -1022,6 +1022,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
|||||||
unsigned short l = 0;
|
unsigned short l = 0;
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
uint16_t type = cmd2type[hdr->command];
|
uint16_t type = cmd2type[hdr->command];
|
||||||
|
bool exist;
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_NHT)
|
if (IS_ZEBRA_DEBUG_NHT)
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
|||||||
p.family);
|
p.family);
|
||||||
return;
|
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 (type == RNH_NEXTHOP_TYPE) {
|
||||||
if (flags
|
if (flags
|
||||||
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
&& !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));
|
zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
|
||||||
/* Anything not AF_INET/INET6 has been filtered out above */
|
/* 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:
|
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. */
|
/* MRIB Nexthop lookup for IPv4. */
|
||||||
static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
|
static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
@ -1794,417 +1604,6 @@ stream_failure:
|
|||||||
return;
|
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 */
|
/* Register zebra server router-id information. Send current router-id */
|
||||||
static void zread_router_id_add(ZAPI_HANDLER_ARGS)
|
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_INTERFACE_DELETE] = zread_interface_delete,
|
||||||
[ZEBRA_ROUTE_ADD] = zread_route_add,
|
[ZEBRA_ROUTE_ADD] = zread_route_add,
|
||||||
[ZEBRA_ROUTE_DELETE] = zread_route_del,
|
[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_ADD] = zebra_redistribute_add,
|
||||||
[ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
|
[ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
|
||||||
[ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
|
[ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
|
||||||
|
@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
|
|||||||
|
|
||||||
/* filter route selection in following order:
|
/* filter route selection in following order:
|
||||||
* - connected beats other types
|
* - connected beats other types
|
||||||
|
* - if both connected, loopback or vrf wins
|
||||||
* - lower distance beats higher
|
* - lower distance beats higher
|
||||||
* - lower metric beats higher for equal distance
|
* - lower metric beats higher for equal distance
|
||||||
* - last, hence oldest, route wins tie break.
|
* - 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.
|
* route of the set of lowest metric connected routes.
|
||||||
*/
|
*/
|
||||||
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
|
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
|
||||||
if (current->type != ZEBRA_ROUTE_CONNECT
|
if (current->type != ZEBRA_ROUTE_CONNECT)
|
||||||
|| alternate->metric <= current->metric)
|
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 alternate;
|
||||||
|
|
||||||
return current;
|
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. */
|
/* Schedule routes of a particular table (address-family) based on event. */
|
||||||
static void rib_update_table(struct route_table *table,
|
void rib_update_table(struct route_table *table, rib_update_event_t event)
|
||||||
rib_update_event_t event)
|
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct route_entry *re, *next;
|
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. */
|
/* Process routes of interested address-families. */
|
||||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
|
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);
|
rib_update_table(table, event);
|
||||||
|
}
|
||||||
|
|
||||||
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
|
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);
|
rib_update_table(table, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete self installed routes after zebra is relaunched. */
|
/* Delete self installed routes after zebra is relaunched. */
|
||||||
|
@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
|
|||||||
return buf;
|
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_table *table;
|
||||||
struct route_node *rn;
|
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));
|
prefix2str(p, buf, sizeof(buf));
|
||||||
zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
|
zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
|
||||||
buf, type);
|
buf, type);
|
||||||
|
exists = false;
|
||||||
return NULL;
|
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);
|
route_lock_node(rn);
|
||||||
rn->info = rnh;
|
rn->info = rnh;
|
||||||
rnh->node = rn;
|
rnh->node = rn;
|
||||||
}
|
*exists = false;
|
||||||
|
} else
|
||||||
|
*exists = true;
|
||||||
|
|
||||||
route_unlock_node(rn);
|
route_unlock_node(rn);
|
||||||
return (rn->info);
|
return (rn->info);
|
||||||
@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
|
|||||||
route_unlock_node(rn);
|
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,
|
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||||
rnh_type_t type, vrf_id_t vrf_id)
|
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)) {
|
if (!listnode_lookup(rnh->client_list, client)) {
|
||||||
listnode_add(rnh->client_list, client);
|
listnode_add(rnh->client_list, client);
|
||||||
send_client(rnh, client, type,
|
send_client(rnh, client, type, vrf_id);
|
||||||
vrf_id); // Pending: check if its needed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
|
|||||||
{
|
{
|
||||||
struct prefix nh;
|
struct prefix nh;
|
||||||
struct rnh *rnh;
|
struct rnh *rnh;
|
||||||
|
bool exists;
|
||||||
|
|
||||||
addr2hostprefix(pw->af, &pw->nexthop, &nh);
|
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)) {
|
if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
|
||||||
listnode_add(rnh->zebra_pseudowire_list, pw);
|
listnode_add(rnh->zebra_pseudowire_list, pw);
|
||||||
pw->rnh = rnh;
|
pw->rnh = rnh;
|
||||||
|
@ -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,
|
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,
|
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||||
rnh_type_t type);
|
rnh_type_t type);
|
||||||
extern void zebra_free_rnh(struct rnh *rnh);
|
extern void zebra_free_rnh(struct rnh *rnh);
|
||||||
|
@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
|
|||||||
/* `match ip address prefix-list PREFIX_LIST' */
|
/* `match ip address prefix-list PREFIX_LIST' */
|
||||||
|
|
||||||
static route_map_result_t
|
static route_map_result_t
|
||||||
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||||
route_map_object_t type, void *object)
|
route_map_object_t type, void *object, afi_t afi)
|
||||||
{
|
{
|
||||||
struct prefix_list *plist;
|
struct prefix_list *plist;
|
||||||
|
|
||||||
if (type == RMAP_ZEBRA) {
|
if (type == RMAP_ZEBRA) {
|
||||||
plist = prefix_list_lookup(AFI_IP, (char *)rule);
|
plist = prefix_list_lookup(afi, (char *)rule);
|
||||||
if (plist == NULL)
|
if (plist == NULL)
|
||||||
return RMAP_NOMATCH;
|
return RMAP_NOMATCH;
|
||||||
|
|
||||||
@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
|||||||
return RMAP_NOMATCH;
|
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);
|
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);
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
|
static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
|
||||||
"ip address prefix-list", route_match_ip_address_prefix_list,
|
"ip address prefix-list", route_match_ip_address_prefix_list,
|
||||||
route_match_ip_address_prefix_list_compile,
|
route_match_address_prefix_list_compile,
|
||||||
route_match_ip_address_prefix_list_free};
|
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' */
|
/* `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,
|
"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)
|
static void zebra_route_map_process_update_cb(char *rmap_name)
|
||||||
{
|
{
|
||||||
if (IS_ZEBRA_DEBUG_EVENT)
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
zlog_debug("Event handler for route-map: %s",
|
zlog_debug("Event handler for route-map: %s",
|
||||||
rmap_name);
|
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)
|
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>
|
* 1) VRF Aware <sigh>
|
||||||
* 2) Route-map aware
|
* 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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1555,12 +1660,19 @@ void zebra_route_map_init()
|
|||||||
route_map_match_tag_hook(generic_match_add);
|
route_map_match_tag_hook(generic_match_add);
|
||||||
route_map_no_match_tag_hook(generic_match_delete);
|
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_tag_cmd);
|
||||||
route_map_install_match(&route_match_interface_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_cmd);
|
||||||
route_map_install_match(&route_match_ip_next_hop_prefix_list_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_cmd);
|
||||||
route_map_install_match(&route_match_ip_address_prefix_list_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_ip_address_prefix_len_cmd);
|
||||||
route_map_install_match(&route_match_ipv6_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);
|
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
Loading…
Reference in New Issue
Block a user