mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 07:03:57 +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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -503,4 +503,5 @@ extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi);
|
||||
extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi,
|
||||
struct ipaddr *originator_ip);
|
||||
extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es);
|
||||
extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
|
||||
#endif /* _BGP_EVPN_PRIVATE_H */
|
||||
|
@ -1888,6 +1888,14 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
|
||||
|
||||
vpn = bgp_evpn_lookup_vni(bgp, vni);
|
||||
if (!vpn) {
|
||||
/* Check if this L2VNI is already configured as L3VNI */
|
||||
if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
|
||||
flog_err(BGP_ERR_VNI,
|
||||
"%u: Failed to create L2VNI %u, it is configured as L3VNI",
|
||||
bgp->vrf_id, vni);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* tenant vrf will be updated when we get local_vni_add from
|
||||
* zebra
|
||||
*/
|
||||
|
@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
|
||||
|
||||
if (BGP_DEBUG(flowspec, FLOWSPEC)) {
|
||||
char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
|
||||
char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX * 2];
|
||||
char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX*2+16];
|
||||
char ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
|
||||
char *s = NULL;
|
||||
|
||||
|
@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
struct listnode *node;
|
||||
struct bgp_pbr_match_entry *bpme;
|
||||
struct bgp_pbr_match *bpm;
|
||||
int unit = 0;
|
||||
bool list_began = false;
|
||||
struct list *list_bpm;
|
||||
|
||||
list_bpm = list_new();
|
||||
@ -347,14 +347,14 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
|
||||
if (listnode_lookup(list_bpm, bpm))
|
||||
continue;
|
||||
listnode_add(list_bpm, bpm);
|
||||
if (unit == 0)
|
||||
if (!list_began) {
|
||||
vty_out(vty, " (");
|
||||
else
|
||||
list_began = true;
|
||||
} else
|
||||
vty_out(vty, ", ");
|
||||
vty_out(vty, "%s", bpm->ipset_name);
|
||||
unit++;
|
||||
}
|
||||
if (unit)
|
||||
if (list_began)
|
||||
vty_out(vty, ")");
|
||||
vty_out(vty, "\n");
|
||||
list_delete_and_null(&list_bpm);
|
||||
|
@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
|
||||
listener->fd = sock;
|
||||
|
||||
/* this socket needs a change of ns. record bgp back pointer */
|
||||
if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
|
||||
if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(
|
||||
vrf_lookup_by_id(bgp->vrf_id)))
|
||||
listener->bgp = bgp;
|
||||
|
||||
memcpy(&listener->su, sa, salen);
|
||||
|
@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
|
||||
? "!" : "",
|
||||
bpf->dscp->val);
|
||||
}
|
||||
zlog_info("BGP: %s FS PBR from %s to %s, %s %s",
|
||||
zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
|
||||
add ? "adding" : "removing",
|
||||
bpf->src == NULL ? "<all>" :
|
||||
prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
|
||||
@ -1807,7 +1807,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
bgp_pbr_match_alloc_intern);
|
||||
|
||||
/* new, then self allocate ipset_name and unique */
|
||||
if (bpm && bpm->unique == 0) {
|
||||
if (bpm->unique == 0) {
|
||||
bpm->unique = ++bgp_pbr_match_counter_unique;
|
||||
/* 0 value is forbidden */
|
||||
sprintf(bpm->ipset_name, "match%p", bpm);
|
||||
@ -1838,10 +1838,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
temp2.src_port_max = src_port ? src_port->max_port : 0;
|
||||
temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
|
||||
temp2.proto = bpf->protocol;
|
||||
if (bpm)
|
||||
bpme = hash_get(bpm->entry_hash, &temp2,
|
||||
bgp_pbr_match_entry_alloc_intern);
|
||||
if (bpme && bpme->unique == 0) {
|
||||
bpme = hash_get(bpm->entry_hash, &temp2,
|
||||
bgp_pbr_match_entry_alloc_intern);
|
||||
if (bpme->unique == 0) {
|
||||
bpme->unique = ++bgp_pbr_match_entry_counter_unique;
|
||||
/* 0 value is forbidden */
|
||||
bpme->backpointer = bpm;
|
||||
@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
|
||||
bpme_found = true;
|
||||
|
||||
/* already installed */
|
||||
if (bpme_found && bpme) {
|
||||
if (bpme_found) {
|
||||
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
|
||||
|
||||
if (extra && extra->bgp_fs_pbr &&
|
||||
|
130
bgpd/bgp_route.c
130
bgpd/bgp_route.c
@ -38,6 +38,7 @@
|
||||
#include "queue.h"
|
||||
#include "memory.h"
|
||||
#include "lib/json.h"
|
||||
#include "lib_errors.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_table.h"
|
||||
@ -188,8 +189,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
|
||||
if (e->parent) {
|
||||
struct bgp_info *bi = (struct bgp_info *)e->parent;
|
||||
|
||||
if (bi->net)
|
||||
bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
|
||||
if (bi->net) {
|
||||
/* FIXME: since multiple e may have the same e->parent
|
||||
* and e->parent->net is holding a refcount for each
|
||||
* of them, we need to do some fudging here.
|
||||
*
|
||||
* WARNING: if bi->net->lock drops to 0, bi may be
|
||||
* freed as well (because bi->net was holding the
|
||||
* last reference to bi) => write after free!
|
||||
*/
|
||||
unsigned refcount;
|
||||
|
||||
bi = bgp_info_lock(bi);
|
||||
refcount = bi->net->lock - 1;
|
||||
bgp_unlock_node((struct bgp_node *)bi->net);
|
||||
if (!refcount)
|
||||
bi->net = NULL;
|
||||
bgp_info_unlock(bi);
|
||||
}
|
||||
bgp_info_unlock(e->parent);
|
||||
e->parent = NULL;
|
||||
}
|
||||
@ -198,8 +215,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
|
||||
bgp_unlock(e->bgp_orig);
|
||||
|
||||
if ((*extra)->bgp_fs_pbr)
|
||||
list_delete_all_node((*extra)->bgp_fs_pbr);
|
||||
(*extra)->bgp_fs_pbr = NULL;
|
||||
list_delete_and_null(&((*extra)->bgp_fs_pbr));
|
||||
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
|
||||
|
||||
*extra = NULL;
|
||||
@ -338,14 +354,9 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
|
||||
/* slight hack, but more robust against errors. */
|
||||
if (ri->peer->pcount[table->afi][table->safi])
|
||||
ri->peer->pcount[table->afi][table->safi]--;
|
||||
else {
|
||||
zlog_warn(
|
||||
"%s: Asked to decrement 0 prefix count for peer %s",
|
||||
__func__, ri->peer->host);
|
||||
zlog_backtrace(LOG_WARNING);
|
||||
zlog_warn("%s: Please report to Quagga bugzilla",
|
||||
__func__);
|
||||
}
|
||||
else
|
||||
flog_err(LIB_ERR_DEVELOPMENT,
|
||||
"Asked to decrement 0 prefix count for peer");
|
||||
} else if (BGP_INFO_COUNTABLE(ri)
|
||||
&& !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
||||
SET_FLAG(ri->flags, BGP_INFO_COUNTED);
|
||||
@ -1039,8 +1050,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
|
||||
|
||||
#define FILTER_EXIST_WARN(F, f, filter) \
|
||||
if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
|
||||
zlog_warn("%s: Could not find configured input %s-list %s!", \
|
||||
peer->host, #f, F##_IN_NAME(filter));
|
||||
zlog_debug("%s: Could not find configured input %s-list %s!", \
|
||||
peer->host, #f, F##_IN_NAME(filter));
|
||||
|
||||
if (DISTRIBUTE_IN_NAME(filter)) {
|
||||
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
|
||||
@ -1078,8 +1089,8 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
|
||||
|
||||
#define FILTER_EXIST_WARN(F, f, filter) \
|
||||
if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
|
||||
zlog_warn("%s: Could not find configured output %s-list %s!", \
|
||||
peer->host, #f, F##_OUT_NAME(filter));
|
||||
zlog_debug("%s: Could not find configured output %s-list %s!", \
|
||||
peer->host, #f, F##_OUT_NAME(filter));
|
||||
|
||||
if (DISTRIBUTE_OUT_NAME(filter)) {
|
||||
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
|
||||
@ -8187,7 +8198,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||
vty_out(vty, " \"routeDistinguishers\" : {");
|
||||
++*json_header_depth;
|
||||
}
|
||||
json_paths = json_object_new_object();
|
||||
}
|
||||
|
||||
if (use_json && rd) {
|
||||
@ -8414,8 +8424,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||
*total_cum = total_count;
|
||||
}
|
||||
if (use_json) {
|
||||
if (json_paths)
|
||||
json_object_free(json_paths);
|
||||
if (rd) {
|
||||
vty_out(vty, " }%s ", (is_last ? "" : ","));
|
||||
}
|
||||
@ -8573,9 +8581,19 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
int count = 0;
|
||||
int best = 0;
|
||||
int suppress = 0;
|
||||
int accept_own = 0;
|
||||
int route_filter_translated_v4 = 0;
|
||||
int route_filter_v4 = 0;
|
||||
int route_filter_translated_v6 = 0;
|
||||
int route_filter_v6 = 0;
|
||||
int llgr_stale = 0;
|
||||
int no_llgr = 0;
|
||||
int accept_own_nexthop = 0;
|
||||
int blackhole = 0;
|
||||
int no_export = 0;
|
||||
int no_advertise = 0;
|
||||
int local_as = 0;
|
||||
int no_peer = 0;
|
||||
int first = 1;
|
||||
int has_valid_label = 0;
|
||||
mpls_label_t label = 0;
|
||||
@ -8652,12 +8670,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
} else
|
||||
vty_out(vty, ", no best path");
|
||||
|
||||
if (no_advertise)
|
||||
vty_out(vty, ", not advertised to any peer");
|
||||
if (accept_own)
|
||||
vty_out(vty,
|
||||
", accept own local route exported and imported in different VRF");
|
||||
else if (route_filter_translated_v4)
|
||||
vty_out(vty,
|
||||
", mark translated RTs for VPNv4 route filtering");
|
||||
else if (route_filter_v4)
|
||||
vty_out(vty,
|
||||
", attach RT as-is for VPNv4 route filtering");
|
||||
else if (route_filter_translated_v6)
|
||||
vty_out(vty,
|
||||
", mark translated RTs for VPNv6 route filtering");
|
||||
else if (route_filter_v6)
|
||||
vty_out(vty,
|
||||
", attach RT as-is for VPNv6 route filtering");
|
||||
else if (llgr_stale)
|
||||
vty_out(vty,
|
||||
", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
|
||||
else if (no_llgr)
|
||||
vty_out(vty,
|
||||
", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
|
||||
else if (accept_own_nexthop)
|
||||
vty_out(vty,
|
||||
", accept local nexthop");
|
||||
else if (blackhole)
|
||||
vty_out(vty, ", inform peer to blackhole prefix");
|
||||
else if (no_export)
|
||||
vty_out(vty, ", not advertised to EBGP peer");
|
||||
else if (no_advertise)
|
||||
vty_out(vty, ", not advertised to any peer");
|
||||
else if (local_as)
|
||||
vty_out(vty, ", not advertised outside local AS");
|
||||
else if (no_peer)
|
||||
vty_out(vty,
|
||||
", inform EBGP peer not to advertise to their EBGP peers");
|
||||
|
||||
if (suppress)
|
||||
vty_out(vty,
|
||||
@ -9018,6 +9065,10 @@ DEFUN (show_ip_bgp,
|
||||
|prefix-list WORD\
|
||||
|filter-list WORD\
|
||||
|statistics\
|
||||
|community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
|
||||
no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
|
||||
route-filter-v6|route-filter-v4|route-filter-translated-v6|\
|
||||
route-filter-translated-v4> [exact-match]\
|
||||
|community-list <(1-500)|WORD> [exact-match]\
|
||||
|A.B.C.D/M longer-prefixes\
|
||||
|X:X::X:X/M longer-prefixes\
|
||||
@ -9037,6 +9088,23 @@ DEFUN (show_ip_bgp,
|
||||
"Display routes conforming to the filter-list\n"
|
||||
"Regular expression access list name\n"
|
||||
"BGP RIB advertisement statistics\n"
|
||||
"Display routes matching the communities\n"
|
||||
COMMUNITY_AANN_STR
|
||||
"Do not send outside local AS (well-known community)\n"
|
||||
"Do not advertise to any peer (well-known community)\n"
|
||||
"Do not export to next AS (well-known community)\n"
|
||||
"Graceful shutdown (well-known community)\n"
|
||||
"Do not export to any peer (well-known community)\n"
|
||||
"Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
|
||||
"Staled Long-lived Graceful Restart VPN route (well-known community)\n"
|
||||
"Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
|
||||
"Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
|
||||
"Should accept VPN route with local nexthop (well-known community)\n"
|
||||
"RT VPNv6 route filtering (well-known community)\n"
|
||||
"RT VPNv4 route filtering (well-known community)\n"
|
||||
"RT translated VPNv6 route filtering (well-known community)\n"
|
||||
"RT translated VPNv4 route filtering (well-known community)\n"
|
||||
"Exact match of the communities\n"
|
||||
"Display routes matching the community-list\n"
|
||||
"community-list number\n"
|
||||
"community-list name\n"
|
||||
@ -9797,8 +9865,6 @@ static int bgp_peer_count_walker(struct thread *t)
|
||||
pc->count[PCOUNT_ADJ_IN]++;
|
||||
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
char buf[SU_ADDRSTRLEN];
|
||||
|
||||
if (ri->peer != peer)
|
||||
continue;
|
||||
|
||||
@ -9820,22 +9886,12 @@ static int bgp_peer_count_walker(struct thread *t)
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
|
||||
pc->count[PCOUNT_COUNTED]++;
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
||||
zlog_warn(
|
||||
"%s [pcount] %s/%d is counted but flags 0x%x",
|
||||
peer->host,
|
||||
inet_ntop(rn->p.family,
|
||||
&rn->p.u.prefix, buf,
|
||||
SU_ADDRSTRLEN),
|
||||
rn->p.prefixlen, ri->flags);
|
||||
flog_err(LIB_ERR_DEVELOPMENT,
|
||||
"Attempting to count but flags say it is unusable");
|
||||
} else {
|
||||
if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
|
||||
zlog_warn(
|
||||
"%s [pcount] %s/%d not counted but flags 0x%x",
|
||||
peer->host,
|
||||
inet_ntop(rn->p.family,
|
||||
&rn->p.u.prefix, buf,
|
||||
SU_ADDRSTRLEN),
|
||||
rn->p.prefixlen, ri->flags);
|
||||
flog_err(LIB_ERR_DEVELOPMENT,
|
||||
"Not counted but flags say we should");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
129
bgpd/bgp_rpki.c
129
bgpd/bgp_rpki.c
@ -47,6 +47,7 @@
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_aspath.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "lib/network.h"
|
||||
#include "lib/thread.h"
|
||||
#include "rtrlib/rtrlib.h"
|
||||
#include "rtrlib/rtr_mgr.h"
|
||||
@ -131,12 +132,14 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix,
|
||||
static void *route_match_compile(const char *arg);
|
||||
static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
|
||||
safi_t safi);
|
||||
static void revalidate_all_routes(void);
|
||||
|
||||
static struct rtr_mgr_config *rtr_config;
|
||||
static struct list *cache_list;
|
||||
static int rtr_is_running;
|
||||
static int rtr_is_stopping;
|
||||
static int rtr_is_starting;
|
||||
static _Atomic int rtr_update_overflow;
|
||||
static int rpki_debug;
|
||||
static unsigned int polling_period;
|
||||
static unsigned int expire_interval;
|
||||
@ -229,7 +232,7 @@ static void *route_match_compile(const char *arg)
|
||||
{
|
||||
int *rpki_status;
|
||||
|
||||
rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
|
||||
rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
|
||||
|
||||
if (strcmp(arg, "valid") == 0)
|
||||
*rpki_status = RPKI_VALID;
|
||||
@ -345,6 +348,19 @@ static int bgpd_sync_callback(struct thread *thread)
|
||||
|
||||
thread_add_read(bm->master, bgpd_sync_callback, NULL,
|
||||
rpki_sync_socket_bgpd, NULL);
|
||||
|
||||
if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
|
||||
while (read(rpki_sync_socket_bgpd, &rec,
|
||||
sizeof(struct pfx_record))
|
||||
!= -1)
|
||||
;
|
||||
|
||||
atomic_store_explicit(&rtr_update_overflow, 0,
|
||||
memory_order_seq_cst);
|
||||
revalidate_all_routes();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retval =
|
||||
read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
|
||||
if (retval != sizeof(struct pfx_record)) {
|
||||
@ -356,26 +372,36 @@ static int bgpd_sync_callback(struct thread *thread)
|
||||
afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
|
||||
safi_t safi;
|
||||
struct peer *peer;
|
||||
struct listnode *peer_listnode;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
if (!bgp->rib[afi][safi])
|
||||
continue;
|
||||
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
|
||||
safi_t safi;
|
||||
|
||||
struct list *matches = list_new();
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
if (!peer->bgp->rib[afi][safi])
|
||||
continue;
|
||||
|
||||
matches->del = (void (*)(void *))bgp_unlock_node;
|
||||
struct list *matches = list_new();
|
||||
|
||||
bgp_table_range_lookup(bgp->rib[afi][safi], prefix,
|
||||
rec.max_len, matches);
|
||||
matches->del =
|
||||
(void (*)(void *))bgp_unlock_node;
|
||||
|
||||
bgp_table_range_lookup(
|
||||
peer->bgp->rib[afi][safi], prefix,
|
||||
rec.max_len, matches);
|
||||
|
||||
|
||||
struct bgp_node *bgp_node;
|
||||
struct bgp_node *bgp_node;
|
||||
struct listnode *bgp_listnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node))
|
||||
revalidate_bgp_node(bgp_node, afi, safi);
|
||||
for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
|
||||
bgp_node))
|
||||
revalidate_bgp_node(bgp_node, afi,
|
||||
safi);
|
||||
|
||||
list_delete_and_null(&matches);
|
||||
list_delete_and_null(&matches);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,14 +424,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
|
||||
label = bgp_info->extra->label;
|
||||
num_labels = bgp_info->extra->num_labels;
|
||||
}
|
||||
ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi,
|
||||
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
|
||||
label, num_labels, 1, NULL);
|
||||
ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id,
|
||||
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
|
||||
BGP_ROUTE_NORMAL, NULL, label, num_labels, 1,
|
||||
NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
bgp_unlock_node(bgp_node);
|
||||
if (ret < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,25 +438,23 @@ static void revalidate_all_routes(void)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct listnode *node;
|
||||
struct bgp_node *bgp_node;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
safi_t safi;
|
||||
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
|
||||
struct peer *peer;
|
||||
struct listnode *peer_listnode;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
|
||||
if (!bgp->rib[afi][safi])
|
||||
continue;
|
||||
for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
|
||||
|
||||
for (bgp_node =
|
||||
bgp_table_top(bgp->rib[afi][safi]);
|
||||
bgp_node;
|
||||
bgp_node = bgp_route_next(bgp_node)) {
|
||||
if (bgp_node->info != NULL) {
|
||||
revalidate_bgp_node(bgp_node,
|
||||
afi, safi);
|
||||
}
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
safi_t safi;
|
||||
afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX;
|
||||
safi++) {
|
||||
if (!peer->bgp->rib[afi][safi])
|
||||
continue;
|
||||
|
||||
bgp_soft_reconfig_in(peer, afi, safi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,28 +465,53 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
|
||||
const struct pfx_record rec,
|
||||
const bool added __attribute__((unused)))
|
||||
{
|
||||
if (rtr_is_stopping || rtr_is_starting)
|
||||
if (rtr_is_stopping || rtr_is_starting
|
||||
|| atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
|
||||
return;
|
||||
|
||||
int retval =
|
||||
write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
|
||||
if (retval != sizeof(struct pfx_record))
|
||||
if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
atomic_store_explicit(&rtr_update_overflow, 1,
|
||||
memory_order_seq_cst);
|
||||
|
||||
else if (retval != sizeof(struct pfx_record))
|
||||
RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
|
||||
}
|
||||
|
||||
static void rpki_init_sync_socket(void)
|
||||
{
|
||||
int fds[2];
|
||||
const char *msg;
|
||||
|
||||
RPKI_DEBUG("initializing sync socket");
|
||||
if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
|
||||
RPKI_DEBUG("Could not open rpki sync socket");
|
||||
return;
|
||||
msg = "could not open rpki sync socketpair";
|
||||
goto err;
|
||||
}
|
||||
rpki_sync_socket_rtr = fds[0];
|
||||
rpki_sync_socket_bgpd = fds[1];
|
||||
|
||||
if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
|
||||
msg = "could not set rpki_sync_socket_rtr to non blocking";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
|
||||
msg = "could not set rpki_sync_socket_bgpd to non blocking";
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
thread_add_read(bm->master, bgpd_sync_callback, NULL,
|
||||
rpki_sync_socket_bgpd, NULL);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
zlog_err("RPKI: %s", msg);
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
static int bgp_rpki_init(struct thread_master *master)
|
||||
@ -514,6 +562,7 @@ static int start(void)
|
||||
|
||||
rtr_is_stopping = 0;
|
||||
rtr_is_starting = 1;
|
||||
rtr_update_overflow = 0;
|
||||
|
||||
if (list_isempty(cache_list)) {
|
||||
RPKI_DEBUG(
|
||||
@ -1210,10 +1259,10 @@ DEFUN_NOSH (rpki_exit,
|
||||
"exit",
|
||||
"Exit rpki configuration and restart rpki session\n")
|
||||
{
|
||||
int ret = reset(false);
|
||||
reset(false);
|
||||
|
||||
vty->node = CONFIG_NODE;
|
||||
return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_NOSH (rpki_quit,
|
||||
|
@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
|
||||
/*
|
||||
* bgp_unlock_node
|
||||
*/
|
||||
static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node)
|
||||
static inline void bgp_unlock_node(struct bgp_node *node)
|
||||
{
|
||||
return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node));
|
||||
route_unlock_node(bgp_node_to_rnode(node));
|
||||
}
|
||||
|
||||
/*
|
||||
|
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. */
|
||||
#if CONFDATE > 20180517
|
||||
#if CONFDATE > 20190517
|
||||
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
|
||||
#endif
|
||||
|
||||
@ -10995,7 +10995,7 @@ DEFUN (show_ip_bgp_attr_info,
|
||||
}
|
||||
|
||||
static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
|
||||
afi_t afi, safi_t safi)
|
||||
afi_t afi, safi_t safi, uint8_t use_json)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct listnode *node;
|
||||
@ -11004,64 +11004,148 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
|
||||
char *ecom_str;
|
||||
vpn_policy_direction_t dir;
|
||||
|
||||
if (name) {
|
||||
bgp = bgp_lookup_by_name(name);
|
||||
if (use_json) {
|
||||
json_object *json = NULL;
|
||||
json_object *json_import_vrfs = NULL;
|
||||
json_object *json_export_vrfs = NULL;
|
||||
|
||||
json = json_object_new_object();
|
||||
|
||||
/* Provide context for the block */
|
||||
json_object_string_add(json, "vrf", name ? name : "default");
|
||||
json_object_string_add(json, "afiSafi",
|
||||
afi_safi_print(afi, safi));
|
||||
|
||||
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
|
||||
|
||||
if (!bgp) {
|
||||
json_object_boolean_true_add(json,
|
||||
"bgpNoSuchInstance");
|
||||
vty_out(vty, "%s\n",
|
||||
json_object_to_json_string_ext(
|
||||
json,
|
||||
JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
|
||||
json_object_string_add(json, "importFromVrfs", "none");
|
||||
json_object_string_add(json, "importRts", "none");
|
||||
} else {
|
||||
json_import_vrfs = json_object_new_array();
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
bgp->vpn_policy[afi].import_vrf,
|
||||
node, vname))
|
||||
json_object_array_add(json_import_vrfs,
|
||||
json_object_new_string(vname));
|
||||
|
||||
dir = BGP_VPN_POLICY_DIR_FROMVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
json_object_object_add(json, "importFromVrfs",
|
||||
json_import_vrfs);
|
||||
json_object_string_add(json, "importRts", ecom_str);
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
|
||||
json_object_string_add(json, "exportToVrfs", "none");
|
||||
json_object_string_add(json, "routeDistinguisher",
|
||||
"none");
|
||||
json_object_string_add(json, "exportRts", "none");
|
||||
} else {
|
||||
json_export_vrfs = json_object_new_array();
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
bgp->vpn_policy[afi].export_vrf,
|
||||
node, vname))
|
||||
json_object_array_add(json_export_vrfs,
|
||||
json_object_new_string(vname));
|
||||
json_object_object_add(json, "exportToVrfs",
|
||||
json_export_vrfs);
|
||||
json_object_string_add(json, "routeDistinguisher",
|
||||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
|
||||
buf1, RD_ADDRSTRLEN));
|
||||
|
||||
dir = BGP_VPN_POLICY_DIR_TOVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
json_object_string_add(json, "exportRts", ecom_str);
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
vty_out(vty, "%s\n",
|
||||
json_object_to_json_string_ext(json,
|
||||
JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
|
||||
} else {
|
||||
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
|
||||
|
||||
if (!bgp) {
|
||||
vty_out(vty, "%% No such BGP instance exist\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
} else {
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp) {
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_IMPORT))
|
||||
vty_out(vty,
|
||||
"%% Default BGP instance does not exist\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
}
|
||||
"This VRF is not importing %s routes from any other VRF\n",
|
||||
afi_safi_print(afi, safi));
|
||||
else {
|
||||
vty_out(vty,
|
||||
"This VRF is importing %s routes from the following VRFs:\n",
|
||||
afi_safi_print(afi, safi));
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
|
||||
vty_out(vty,
|
||||
"This VRF is not importing %s routes from any other VRF\n",
|
||||
afi_safi_print(afi, safi));
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"This VRF is importing %s routes from the following VRFs:\n",
|
||||
afi_safi_print(afi, safi));
|
||||
for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
|
||||
vname)) {
|
||||
vty_out(vty, " %s\n", vname);
|
||||
}
|
||||
dir = BGP_VPN_POLICY_DIR_FROMVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, "Import RT(s): %s\n", ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
bgp->vpn_policy[afi].import_vrf,
|
||||
node, vname))
|
||||
vty_out(vty, " %s\n", vname);
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
|
||||
vty_out(vty,
|
||||
"This VRF is not exporting %s routes to any other VRF\n",
|
||||
afi_safi_print(afi, safi));
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"This VRF is exporting %s routes to the following VRFs:\n",
|
||||
afi_safi_print(afi, safi));
|
||||
for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].export_vrf, node,
|
||||
vname)) {
|
||||
vty_out(vty, " %s\n", vname);
|
||||
dir = BGP_VPN_POLICY_DIR_FROMVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, "Import RT(s): %s\n", ecom_str);
|
||||
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_VRF_TO_VRF_EXPORT))
|
||||
vty_out(vty,
|
||||
"This VRF is not exporting %s routes to any other VRF\n",
|
||||
afi_safi_print(afi, safi));
|
||||
else {
|
||||
vty_out(vty,
|
||||
"This VRF is exporting %s routes to the following VRFs:\n",
|
||||
afi_safi_print(afi, safi));
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(
|
||||
bgp->vpn_policy[afi].export_vrf,
|
||||
node, vname))
|
||||
vty_out(vty, " %s\n", vname);
|
||||
|
||||
vty_out(vty, "RD: %s\n",
|
||||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
|
||||
buf1, RD_ADDRSTRLEN));
|
||||
|
||||
dir = BGP_VPN_POLICY_DIR_TOVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, "Export RT: %s\n", ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
vty_out(vty, "RD: %s\n",
|
||||
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
|
||||
buf1, RD_ADDRSTRLEN));
|
||||
dir = BGP_VPN_POLICY_DIR_TOVPN;
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
bgp->vpn_policy[afi].rtlist[dir],
|
||||
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, "Emport RT: %s\n", ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -11069,20 +11153,22 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
|
||||
|
||||
/* "show [ip] bgp route-leak" command. */
|
||||
DEFUN (show_ip_bgp_route_leak,
|
||||
show_ip_bgp_route_leak_cmd,
|
||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
BGP_STR
|
||||
BGP_INSTANCE_HELP_STR
|
||||
BGP_AFI_HELP_STR
|
||||
BGP_SAFI_HELP_STR
|
||||
"Route leaking information\n")
|
||||
show_ip_bgp_route_leak_cmd,
|
||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
BGP_STR
|
||||
BGP_INSTANCE_HELP_STR
|
||||
BGP_AFI_HELP_STR
|
||||
BGP_SAFI_HELP_STR
|
||||
"Route leaking information\n"
|
||||
JSON_STR)
|
||||
{
|
||||
char *vrf = NULL;
|
||||
afi_t afi = AFI_MAX;
|
||||
safi_t safi = SAFI_MAX;
|
||||
|
||||
uint8_t uj = use_json(argc, argv);
|
||||
int idx = 0;
|
||||
|
||||
/* show [ip] bgp */
|
||||
@ -11110,7 +11196,7 @@ DEFUN (show_ip_bgp_route_leak,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return bgp_show_route_leak_vty(vty, vrf, afi, safi);
|
||||
return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj);
|
||||
}
|
||||
|
||||
static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
|
||||
@ -11462,7 +11548,7 @@ DEFUN (bgp_redistribute_ipv4,
|
||||
}
|
||||
|
||||
bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0, false);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11483,6 +11569,7 @@ DEFUN (bgp_redistribute_ipv4_rmap,
|
||||
int idx_word = 3;
|
||||
int type;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11491,8 +11578,8 @@ DEFUN (bgp_redistribute_ipv4_rmap,
|
||||
}
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11516,6 +11603,7 @@ DEFUN (bgp_redistribute_ipv4_metric,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11525,8 +11613,8 @@ DEFUN (bgp_redistribute_ipv4_metric,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11553,6 +11641,7 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11562,9 +11651,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11595,6 +11684,7 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11604,9 +11694,9 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, type, 0);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
|
||||
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11642,7 +11732,7 @@ DEFUN (bgp_redistribute_ipv4_ospf,
|
||||
protocol = ZEBRA_ROUTE_TABLE;
|
||||
|
||||
bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, false);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd,
|
||||
@ -11669,6 +11759,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
|
||||
struct bgp_redist *red;
|
||||
unsigned short instance;
|
||||
int protocol;
|
||||
bool changed;
|
||||
|
||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||
protocol = ZEBRA_ROUTE_OSPF;
|
||||
@ -11677,8 +11768,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
|
||||
|
||||
instance = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
|
||||
@ -11709,6 +11800,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
|
||||
struct bgp_redist *red;
|
||||
unsigned short instance;
|
||||
int protocol;
|
||||
bool changed;
|
||||
|
||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||
protocol = ZEBRA_ROUTE_OSPF;
|
||||
@ -11719,8 +11811,9 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
|
||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||
metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
|
||||
@ -11754,6 +11847,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
|
||||
struct bgp_redist *red;
|
||||
unsigned short instance;
|
||||
int protocol;
|
||||
bool changed;
|
||||
|
||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||
protocol = ZEBRA_ROUTE_OSPF;
|
||||
@ -11764,9 +11858,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
|
||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||
metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11803,6 +11898,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
|
||||
struct bgp_redist *red;
|
||||
unsigned short instance;
|
||||
int protocol;
|
||||
bool changed;
|
||||
|
||||
if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
|
||||
protocol = ZEBRA_ROUTE_OSPF;
|
||||
@ -11813,9 +11909,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
|
||||
metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
|
||||
metric);
|
||||
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
|
||||
}
|
||||
|
||||
ALIAS_HIDDEN(
|
||||
@ -11923,7 +12020,7 @@ DEFUN (bgp_redistribute_ipv6,
|
||||
}
|
||||
|
||||
bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, false);
|
||||
}
|
||||
|
||||
DEFUN (bgp_redistribute_ipv6_rmap,
|
||||
@ -11939,6 +12036,7 @@ DEFUN (bgp_redistribute_ipv6_rmap,
|
||||
int idx_word = 3;
|
||||
int type;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11947,8 +12045,8 @@ DEFUN (bgp_redistribute_ipv6_rmap,
|
||||
}
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||
}
|
||||
|
||||
DEFUN (bgp_redistribute_ipv6_metric,
|
||||
@ -11965,6 +12063,7 @@ DEFUN (bgp_redistribute_ipv6_metric,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -11974,8 +12073,8 @@ DEFUN (bgp_redistribute_ipv6_metric,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||
}
|
||||
|
||||
DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
||||
@ -11995,6 +12094,7 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -12004,9 +12104,10 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
||||
changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type,
|
||||
metric);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||
}
|
||||
|
||||
DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
||||
@ -12026,6 +12127,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
||||
int type;
|
||||
uint32_t metric;
|
||||
struct bgp_redist *red;
|
||||
bool changed;
|
||||
|
||||
type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
|
||||
if (type < 0) {
|
||||
@ -12035,9 +12137,10 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
|
||||
metric = strtoul(argv[idx_number]->arg, NULL, 10);
|
||||
|
||||
red = bgp_redist_add(bgp, AFI_IP6, type, 0);
|
||||
bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric);
|
||||
bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
|
||||
changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST,
|
||||
metric);
|
||||
changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
|
||||
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_redistribute_ipv6,
|
||||
|
@ -1576,8 +1576,14 @@ static void bgp_redist_del(struct bgp *bgp, afi_t afi, uint8_t type,
|
||||
|
||||
/* Other routes redistribution into BGP. */
|
||||
int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
|
||||
unsigned short instance)
|
||||
unsigned short instance, bool changed)
|
||||
{
|
||||
/* If redistribute options are changed call
|
||||
* bgp_redistribute_unreg() to reset the option and withdraw
|
||||
* the routes
|
||||
*/
|
||||
if (changed)
|
||||
bgp_redistribute_unreg(bgp, afi, type, instance);
|
||||
|
||||
/* Return if already redistribute flag is set. */
|
||||
if (instance) {
|
||||
|
@ -51,7 +51,8 @@ extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t,
|
||||
unsigned short);
|
||||
extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
|
||||
unsigned short);
|
||||
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short);
|
||||
extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short,
|
||||
bool changed);
|
||||
extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short);
|
||||
extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
|
||||
extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
|
||||
|
22
bgpd/bgpd.c
22
bgpd/bgpd.c
@ -3187,15 +3187,16 @@ int bgp_delete(struct bgp *bgp)
|
||||
.import_redirect_rtlist);
|
||||
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
|
||||
}
|
||||
/* Remove visibility via the master list - there may however still be
|
||||
* routes to be processed still referencing the struct bgp.
|
||||
*/
|
||||
listnode_delete(bm->bgp, bgp);
|
||||
|
||||
/* Deregister from Zebra, if needed */
|
||||
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
|
||||
bgp_zebra_instance_deregister(bgp);
|
||||
|
||||
/* Remove visibility via the master list - there may however still be
|
||||
* routes to be processed still referencing the struct bgp.
|
||||
*/
|
||||
listnode_delete(bm->bgp, bgp);
|
||||
|
||||
/* Free interfaces in this instance. */
|
||||
bgp_if_finish(bgp);
|
||||
|
||||
@ -6631,17 +6632,6 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json,
|
||||
time_t uptime1, epoch_tbuf;
|
||||
struct tm *tm;
|
||||
|
||||
/* Check buffer length. */
|
||||
if (len < BGP_UPTIME_LEN) {
|
||||
if (!use_json) {
|
||||
zlog_warn("peer_uptime (): buffer shortage %lu",
|
||||
(unsigned long)len);
|
||||
/* XXX: should return status instead of buf... */
|
||||
snprintf(buf, len, "<error> ");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* If there is no connection has been done before print `never'. */
|
||||
if (uptime2 == 0) {
|
||||
if (use_json) {
|
||||
@ -7356,7 +7346,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#if CONFDATE > 20180517
|
||||
#if CONFDATE > 20190517
|
||||
CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
13
configure.ac
13
configure.ac
@ -382,7 +382,7 @@ AC_ARG_ENABLE(bgp-vnc,
|
||||
AC_ARG_WITH(rfp-path,
|
||||
AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
|
||||
AC_ARG_ENABLE(snmp,
|
||||
AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)]))
|
||||
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
|
||||
AC_ARG_ENABLE(zeromq,
|
||||
AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
|
||||
AC_ARG_WITH(libpam,
|
||||
@ -418,8 +418,6 @@ AC_ARG_ENABLE(rusage,
|
||||
AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
|
||||
AC_ARG_ENABLE(gcc_ultra_verbose,
|
||||
AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings]))
|
||||
AC_ARG_ENABLE(linux24_tcp_md5,
|
||||
AS_HELP_STRING([--enable-linux24-tcp-md5], [enable support for old, Linux-2.4 RFC2385 patch]))
|
||||
AC_ARG_ENABLE(backtrace,
|
||||
AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
|
||||
AC_ARG_ENABLE(time-check,
|
||||
@ -644,10 +642,6 @@ AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
|
||||
# End of logic for protobuf support.
|
||||
#
|
||||
|
||||
if test "${enable_linux24_tcp_md5}" = "yes"; then
|
||||
AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements)
|
||||
if test "${enable_rtadv}" != "no"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
@ -1496,14 +1490,13 @@ int main(void);
|
||||
yes)
|
||||
SNMP_METHOD=agentx
|
||||
;;
|
||||
smux|agentx)
|
||||
agentx)
|
||||
SNMP_METHOD="${enable_snmp}"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use smux or agentx])
|
||||
AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use yes or agentx])
|
||||
;;
|
||||
esac
|
||||
AH_TEMPLATE([SNMP_SMUX], [Use SNMP SMUX to interface with snmpd])
|
||||
AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd])
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
|
||||
fi
|
||||
|
@ -10,7 +10,6 @@
|
||||
WANT_LDP ?= 1
|
||||
WANT_PIM ?= 1
|
||||
WANT_OSPFAPI ?= 1
|
||||
WANT_TCP_ZEBRA ?= 0
|
||||
WANT_BGP_VNC ?= 1
|
||||
WANT_CUMULUS_MODE ?= 0
|
||||
WANT_MULTIPATH ?= 1
|
||||
@ -65,12 +64,6 @@ else
|
||||
USE_OSPFAPI=--enable-ospfapi=no
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_TCP_ZEBRA),1)
|
||||
USE_TCP_ZEBRA=--enable-tcp-zebra
|
||||
else
|
||||
USE_TCP_ZEBRA=--disable-tcp-zebra
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_BGP_VNC), 1)
|
||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||
else
|
||||
@ -123,7 +116,6 @@ override_dh_auto_configure:
|
||||
$(USE_OSPFAPI) \
|
||||
$(USE_MULTIPATH) \
|
||||
$(USE_LDP) \
|
||||
$(USE_TCP_ZEBRA) \
|
||||
--enable-fpm \
|
||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||
$(USE_FRR_VTY_GROUP) \
|
||||
@ -162,12 +154,8 @@ override_dh_auto_install:
|
||||
mkdir -p debian/tmp/etc/frr/
|
||||
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
|
||||
|
||||
# installing the Frr specific SNMP MIB
|
||||
ifeq ($(WANT_SNMP), 1)
|
||||
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
|
||||
else
|
||||
# leftover from previously shipping SMUX client OID MIB
|
||||
mkdir -p debian/tmp/usr/share/snmp/mibs
|
||||
endif
|
||||
|
||||
# cleaning .la files
|
||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||
|
@ -10,7 +10,6 @@
|
||||
WANT_LDP ?= 1
|
||||
WANT_PIM ?= 1
|
||||
WANT_OSPFAPI ?= 1
|
||||
WANT_TCP_ZEBRA ?= 0
|
||||
WANT_BGP_VNC ?= 1
|
||||
WANT_CUMULUS_MODE ?= 0
|
||||
WANT_MULTIPATH ?= 1
|
||||
@ -75,12 +74,6 @@ else
|
||||
USE_OSPFAPI=--enable-ospfapi=no
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_TCP_ZEBRA),1)
|
||||
USE_TCP_ZEBRA=--enable-tcp-zebra
|
||||
else
|
||||
USE_TCP_ZEBRA=--disable-tcp-zebra
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_BGP_VNC), 1)
|
||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||
else
|
||||
@ -152,7 +145,6 @@ override_dh_auto_configure:
|
||||
$(USE_OSPFAPI) \
|
||||
$(USE_MULTIPATH) \
|
||||
$(USE_LDP) \
|
||||
$(USE_TCP_ZEBRA) \
|
||||
--enable-fpm \
|
||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||
$(USE_FRR_VTY_GROUP) \
|
||||
@ -196,12 +188,8 @@ override_dh_auto_install:
|
||||
mkdir -p debian/tmp/etc/frr/
|
||||
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
|
||||
|
||||
# installing the Frr specific SNMP MIB
|
||||
ifeq ($(WANT_SNMP), 1)
|
||||
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
|
||||
else
|
||||
# leftover from previously shipping SMUX client OID MIB
|
||||
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
||||
endif
|
||||
|
||||
# cleaning .la files
|
||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||
|
@ -10,7 +10,6 @@
|
||||
WANT_LDP ?= 1
|
||||
WANT_PIM ?= 1
|
||||
WANT_OSPFAPI ?= 1
|
||||
WANT_TCP_ZEBRA ?= 0
|
||||
WANT_BGP_VNC ?= 1
|
||||
WANT_CUMULUS_MODE ?= 0
|
||||
WANT_MULTIPATH ?= 1
|
||||
@ -75,12 +74,6 @@ else
|
||||
USE_OSPFAPI=--enable-ospfapi=no
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_TCP_ZEBRA),1)
|
||||
USE_TCP_ZEBRA=--enable-tcp-zebra
|
||||
else
|
||||
USE_TCP_ZEBRA=--disable-tcp-zebra
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_BGP_VNC), 1)
|
||||
USE_BGP_VNC=--enable-bgp-vnc=yes
|
||||
else
|
||||
@ -152,7 +145,6 @@ override_dh_auto_configure:
|
||||
$(USE_OSPFAPI) \
|
||||
$(USE_MULTIPATH) \
|
||||
$(USE_LDP) \
|
||||
$(USE_TCP_ZEBRA) \
|
||||
--enable-fpm \
|
||||
$(USE_FRR_USER) $(USE_FRR_GROUP) \
|
||||
$(USE_FRR_VTY_GROUP) \
|
||||
@ -194,12 +186,8 @@ override_dh_auto_install:
|
||||
mkdir -p debian/tmp/etc/frr/
|
||||
perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
|
||||
|
||||
# installing the Frr specific SNMP MIB
|
||||
ifeq ($(WANT_SNMP), 1)
|
||||
install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
|
||||
else
|
||||
# leftover from previously shipping SMUX client OID MIB
|
||||
mkdir -p debian/tmp/usr/share/snmp/mibs/
|
||||
endif
|
||||
|
||||
# cleaning .la files
|
||||
sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
|
||||
|
@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \
|
||||
developer/index.rst \
|
||||
developer/ldpd-basic-test-setup.md \
|
||||
developer/library.rst \
|
||||
developer/logging.rst \
|
||||
developer/Makefile.in \
|
||||
developer/maintainer-release-build.rst \
|
||||
developer/memtypes.rst \
|
||||
|
@ -7,6 +7,7 @@ Library Facilities (libfrr)
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
logging
|
||||
memtypes
|
||||
hooks
|
||||
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_IPV4_ROUTE_ADD | 7 |
|
||||
+-----------------------------------+-------+
|
||||
| ZEBRA_IPV4_ROUTE_DELETE | 8 |
|
||||
+-----------------------------------+-------+
|
||||
| ZEBRA_IPV6_ROUTE_ADD | 9 |
|
||||
+-----------------------------------+-------+
|
||||
| ZEBRA_IPV6_ROUTE_DELETE | 10 |
|
||||
+-----------------------------------+-------+
|
||||
| ZEBRA_REDISTRIBUTE_ADD | 11 |
|
||||
+-----------------------------------+-------+
|
||||
| ZEBRA_REDISTRIBUTE_DELETE | 12 |
|
||||
|
@ -126,7 +126,7 @@ These following options control the daemon's VTY (interactive command line) inte
|
||||
staticd 2616
|
||||
bfdd 2617
|
||||
|
||||
Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for the (insecure) TCP-ZEBRA interface.
|
||||
Port 2607 is used for ospfd's Opaque LSA API.
|
||||
|
||||
.. option:: --vty_socket vty-path
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
bfdd
|
||||
bgpd
|
||||
eigrpd
|
||||
isisd
|
||||
|
@ -6,3 +6,50 @@ div.body {
|
||||
pre {
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
/* styling for the protocols vs. OS table in overview.rst */
|
||||
/* first, general bits */
|
||||
div.body td.mark {
|
||||
text-align: center;
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
table.mark th {
|
||||
text-align: center;
|
||||
}
|
||||
table.mark td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
table.mark td[colspan="7"] {
|
||||
text-align: center;
|
||||
padding-top: 8pt;
|
||||
padding-bottom: 2pt;
|
||||
}
|
||||
table.mark cite {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* individual Y/N/... cells */
|
||||
td.mark {
|
||||
width: 4.5em;
|
||||
}
|
||||
td.mark span {
|
||||
display: block;
|
||||
padding: 3px 1px;
|
||||
border: 1px dotted #666;
|
||||
width: 36pt;
|
||||
margin:auto;
|
||||
}
|
||||
span.mark-y { background-color: #77ffaa; }
|
||||
span.mark-geq { background-color: #aaff77; }
|
||||
span.mark-cp { background-color: #ffbb55; }
|
||||
span.mark-n { background-color: #ff8877; }
|
||||
span.mark-dag { background-color: #ffee99; font-size: 8pt; padding:0px 1px; border-top:0px; }
|
||||
|
||||
/* for the legend below */
|
||||
li span.mark {
|
||||
display: inline-block;
|
||||
padding: 3px 1px;
|
||||
border: 1px dotted #666;
|
||||
width: 36pt;
|
||||
text-align: center;
|
||||
}
|
||||
|
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:
|
||||
|
||||
OSPF BFD Configuration
|
||||
---------------------
|
||||
----------------------
|
||||
|
||||
The following commands are available inside the interface configuration node.
|
||||
|
||||
@ -364,7 +364,7 @@ You can inspect the current BFD peer status with the following commands:
|
||||
Echo transmission interval: 50ms
|
||||
|
||||
frr# show bfd peer 192.168.0.1 json
|
||||
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
|
||||
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
|
||||
|
||||
|
||||
You can also inspect peer session counters with the following commands:
|
||||
@ -402,4 +402,4 @@ You can also inspect peer session counters with the following commands:
|
||||
Zebra notifications: 4
|
||||
|
||||
frr# show bfd peer 192.168.0.1 counters json
|
||||
{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
|
||||
{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
|
||||
|
@ -1011,6 +1011,75 @@ is 4 octet long. The following format is used to define the community value.
|
||||
``internet``
|
||||
``internet`` represents well-known communities value 0.
|
||||
|
||||
``graceful-shutdown``
|
||||
``graceful-shutdown`` represents well-known communities value
|
||||
``GRACEFUL_SHUTDOWN`` ``0xFFFF0000`` ``65535:0``. :rfc:`8326` implements
|
||||
the purpose Graceful BGP Session Shutdown to reduce the amount of
|
||||
lost traffic when taking BGP sessions down for maintainance. The use
|
||||
of the community needs to be supported from your peers side to
|
||||
actually have any effect.
|
||||
|
||||
``accept-own``
|
||||
``accept-own`` represents well-known communities value ``ACCEPT_OWN``
|
||||
``0xFFFF0001`` ``65535:1``. :rfc:`7611` implements a way to signal
|
||||
to a router to accept routes with a local nexthop address. This
|
||||
can be the case when doing policing and having traffic having a
|
||||
nexthop located in another VRF but still local interface to the
|
||||
router. It is recommended to read the RFC for full details.
|
||||
|
||||
``route-filter-translated-v4``
|
||||
``route-filter-translated-v4`` represents well-known communities value
|
||||
``ROUTE_FILTER_TRANSLATED_v4`` ``0xFFFF0002`` ``65535:2``.
|
||||
|
||||
``route-filter-v4``
|
||||
``route-filter-v4`` represents well-known communities value
|
||||
``ROUTE_FILTER_v4`` ``0xFFFF0003`` ``65535:3``.
|
||||
|
||||
``route-filter-translated-v6``
|
||||
``route-filter-translated-v6`` represents well-known communities value
|
||||
``ROUTE_FILTER_TRANSLATED_v6`` ``0xFFFF0004`` ``65535:4``.
|
||||
|
||||
``route-filter-v6``
|
||||
``route-filter-v6`` represents well-known communities value
|
||||
``ROUTE_FILTER_v6`` ``0xFFFF0005`` ``65535:5``.
|
||||
|
||||
``llgr-stale``
|
||||
``llgr-stale`` represents well-known communities value ``LLGR_STALE``
|
||||
``0xFFFF0006`` ``65535:6``.
|
||||
Assigned and intented only for use with routers supporting the
|
||||
Long-lived Graceful Restart Capability as described in
|
||||
:rfc:`draft-uttaro-idr-bgp-persistence`.
|
||||
Routers recieving routes with this community may (depending on
|
||||
implementation) choose allow to reject or modify routes on the
|
||||
presence or absence of this community.
|
||||
|
||||
``no-llgr``
|
||||
``no-llgr`` represents well-known communities value ``NO_LLGR``
|
||||
``0xFFFF0007`` ``65535:7``.
|
||||
Assigned and intented only for use with routers supporting the
|
||||
Long-lived Graceful Restart Capability as described in
|
||||
:rfc:`draft-uttaro-idr-bgp-persistence`.
|
||||
Routers recieving routes with this community may (depending on
|
||||
implementation) choose allow to reject or modify routes on the
|
||||
presence or absence of this community.
|
||||
|
||||
``accept-own-nexthop``
|
||||
``accept-own-nexthop`` represents well-known communities value
|
||||
``accept-own-nexthop`` ``0xFFFF0008`` ``65535:8``.
|
||||
:rfc:`draft-agrewal-idr-accept-own-nexthop` describes
|
||||
how to tag and label VPN routes to be able to send traffic between VRFs
|
||||
via an internal layer 2 domain on the same PE device. Refer to
|
||||
:rfc:`draft-agrewal-idr-accept-own-nexthop` for full details.
|
||||
|
||||
``blackhole``
|
||||
``blackhole`` represents well-known communities value ``BLACKHOLE``
|
||||
``0xFFFF029A`` ``65535:666``. :rfc:`7999` documents sending prefixes to
|
||||
EBGP peers and upstream for the purpose of blackholing traffic.
|
||||
Prefixes tagged with the this community should normally not be
|
||||
re-advertised from neighbors of the originating network. It is
|
||||
recommended upon receiving prefixes tagged with this community to
|
||||
add ``NO_EXPORT`` and ``NO_ADVERTISE``.
|
||||
|
||||
``no-export``
|
||||
``no-export`` represents well-known communities value ``NO_EXPORT``
|
||||
``0xFFFFFF01``. All routes carry this value must not be advertised to
|
||||
@ -1030,6 +1099,11 @@ is 4 octet long. The following format is used to define the community value.
|
||||
it is considered as external BGP peer, so the route will not be announced to
|
||||
the peer.
|
||||
|
||||
``no-peer``
|
||||
``no-peer`` represents well-known communities value ``NOPEER``
|
||||
``0xFFFFFF04`` ``65535:65284``. :rfc:`3765` is used to communicate to
|
||||
another network how the originating network want the prefix propagated.
|
||||
|
||||
When the communities attribute is received duplicate community values in the
|
||||
attribute are ignored and value is sorted in numerical order.
|
||||
|
||||
|
@ -358,6 +358,7 @@ def setup(app):
|
||||
app.add_object_type('clicmd', 'clicmd')
|
||||
# css overrides for HTML theme
|
||||
app.add_stylesheet('overrides.css')
|
||||
app.add_javascript('overrides.js')
|
||||
# load Pygments lexer for FRR config syntax
|
||||
#
|
||||
# NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we
|
||||
|
@ -5,12 +5,12 @@ Overview
|
||||
********
|
||||
|
||||
`FRR`_ is a routing software package that provides TCP/IP based routing
|
||||
services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2,
|
||||
OSPFv3, IS-IS, BGP-4, and BGP-4+ (:ref:`supported-rfcs`). FRR also supports
|
||||
services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more
|
||||
(see :ref:`supported-protocols`). FRR also supports
|
||||
special BGP Route Reflector and Route Server behavior. In addition to
|
||||
traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols.
|
||||
With SNMP daemon which supports SMUX and AgentX protocol, FRR provides routing
|
||||
protocol MIBs (:ref:`snmp-support`).
|
||||
With an SNMP daemon that supports the AgentX protocol, FRR provides routing
|
||||
protocol MIB read-only access (:ref:`snmp-support`).
|
||||
|
||||
FRR uses an advanced software architecture to provide you with a high quality,
|
||||
multi server routing engine. FRR has an interactive user interface for each
|
||||
@ -150,27 +150,93 @@ Recent versions of the following compilers are well tested:
|
||||
|
||||
.. _supported-protocols:
|
||||
|
||||
Supported Protocols & RFCs
|
||||
==========================
|
||||
Supported Protocols vs. Platform
|
||||
================================
|
||||
|
||||
The following well-known protocols are supported:
|
||||
The following table lists all protocols cross-refrenced to all operating
|
||||
systems that have at least CI build tests. Note that for features, only
|
||||
features with system dependencies are included here.
|
||||
|
||||
- BGP
|
||||
- Babel
|
||||
- EIGRP
|
||||
- IS-IS
|
||||
- LDP
|
||||
- NHRP
|
||||
- OSPFv2
|
||||
- OSPFv3
|
||||
- PIM
|
||||
- RIP
|
||||
- RIPNG
|
||||
.. role:: mark
|
||||
|
||||
The following technologies are supported as well:
|
||||
.. comment - the :mark:`X` pieces mesh with a little bit of JavaScript and
|
||||
CSS in _static/overrides.{js,css} respectively. The JS code looks at the
|
||||
presence of the 'Y' 'N' '≥' '†' or 'CP' strings. This seemed to be the
|
||||
best / least intrusive way of getting a nice table in HTML. The table
|
||||
will look somewhat shoddy on other sphinx targets like PDF or info (but
|
||||
should still be readable.)
|
||||
|
||||
- PBR (Policy Based Routing)
|
||||
- VNC (Virtual Network Control)
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| Daemon / Feature | Linux | OpenBSD | FreeBSD | NetBSD | Solaris |
|
||||
+==+================================+================+==============+============+============+============+
|
||||
| FRR Core |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `zebra` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| WAN / Carrier protocols |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `bgpd` (BGP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
|
||||
| | | :mark:`†4.3` | | | | |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
|
||||
| | | :mark:`†4.9` | | | | |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `ldpd` (LDP) | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| Link-State Routing |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `ospfd` (OSPFv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `ospf6d` (OSPFv3) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `isisd` (IS-IS) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| Distance-Vector Routing |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `ripd` (RIPv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `ripngd` (RIPng) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `babeld` (BABEL) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `eigrpd` (EIGRP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| Multicast Routing |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
| | ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` |
|
||||
+--+--------------------------------+----------------+--------------+------------+------------+------------+
|
||||
|
||||
The indicators have the following semantics:
|
||||
|
||||
* :mark:`Y` - daemon/feature fully functional
|
||||
* :mark:`≥X.X` - fully functional with kernel version X.X or newer
|
||||
* :mark:`†X.X` - restricted functionality or impaired performance with kernel version X.X or newer
|
||||
* :mark:`CP` - control plane only (i.e. BGP route server / route reflector)
|
||||
* :mark:`N` - daemon/feature not supported by operating system
|
||||
|
||||
.. _supported-rfcs:
|
||||
|
||||
|
@ -7,8 +7,8 @@ SNMP Support
|
||||
:abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature
|
||||
for collecting network information from router and/or host. FRR itself does
|
||||
not support SNMP agent (server daemon) functionality but is able to connect to
|
||||
a SNMP agent using the SMUX protocol (:rfc:`1227`) or the AgentX protocol
|
||||
(:rfc:`2741`) and make the routing protocol MIBs available through it.
|
||||
a SNMP agent using the the AgentX protocol (:rfc:`2741`) and make the
|
||||
routing protocol MIBs available through it.
|
||||
|
||||
Note that SNMP Support needs to be enabled at compile-time and loaded as module
|
||||
on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
|
||||
@ -18,16 +18,10 @@ on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
|
||||
Getting and installing an SNMP agent
|
||||
====================================
|
||||
|
||||
There are several SNMP agent which support SMUX or AgentX. We recommend to use
|
||||
The supported SNMP agent is AgentX. We recommend to use
|
||||
the latest version of `net-snmp` which was formerly known as `ucd-snmp`. It is
|
||||
free and open software and available at `http://www.net-snmp.org/ <http://www.net-snmp.org/>`_
|
||||
and as binary package for most Linux distributions. `net-snmp` has to be
|
||||
compiled with `--with-mib-modules=agentx` to be able to accept connections from
|
||||
FRR using AgentX protocol or with `--with-mib-modules=smux` to use SMUX
|
||||
protocol.
|
||||
|
||||
Nowadays, SMUX is a legacy protocol. The AgentX protocol should be preferred
|
||||
for any new deployment. Both protocols have the same coverage.
|
||||
and as binary package for most Linux distributions.
|
||||
|
||||
.. _agentx-configuration:
|
||||
|
||||
@ -42,7 +36,7 @@ master SNMP agent (snmpd) and each of the FRR daemons must be configured. In
|
||||
:file:`/etc/snmp/snmpd.conf`, the ``master agentx`` directive should be added.
|
||||
In each of the FRR daemons, ``agentx`` command will enable AgentX support.
|
||||
|
||||
:file:`/etc/snmp/snmpd.conf`:
|
||||
:file:`/etc/snmp/zebra.conf`:
|
||||
|
||||
::
|
||||
|
||||
@ -97,105 +91,6 @@ need to configure FRR to use another transport, you can configure it through
|
||||
agentXSocket tcp:192.168.15.12:705
|
||||
|
||||
|
||||
.. _smux-configuration:
|
||||
|
||||
SMUX configuration
|
||||
==================
|
||||
|
||||
To enable SMUX protocol support, FRR must have been build with the
|
||||
:option:`--enable-snmp` option.
|
||||
|
||||
A separate connection has then to be established between the SNMP agent (snmpd)
|
||||
and each of the FRR daemons. This connections each use different OID numbers
|
||||
and passwords. Be aware that this OID number is not the one that is used in
|
||||
queries by clients, it is solely used for the intercommunication of the
|
||||
daemons.
|
||||
|
||||
In the following example the ospfd daemon will be connected to the snmpd daemon
|
||||
using the password "frr_ospfd". For testing it is recommending to take exactly
|
||||
the below snmpd.conf as wrong access restrictions can be hard to debug.
|
||||
|
||||
:file:`/etc/snmp/snmpd.conf`:
|
||||
|
||||
::
|
||||
|
||||
#
|
||||
# example access restrictions setup
|
||||
#
|
||||
com2sec readonly default public
|
||||
group MyROGroup v1 readonly
|
||||
view all included .1 80
|
||||
access MyROGroup "" any noauth exact all none none
|
||||
#
|
||||
# the following line is relevant for FRR
|
||||
#
|
||||
smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
|
||||
|
||||
:file:`/etc/frr/ospf`:
|
||||
|
||||
::
|
||||
|
||||
! ... the rest of ospfd.conf has been omitted for clarity ...
|
||||
!
|
||||
smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
|
||||
!
|
||||
|
||||
|
||||
After restarting snmpd and frr, a successful connection can be verified in the
|
||||
syslog and by querying the SNMP daemon:
|
||||
|
||||
::
|
||||
|
||||
snmpd[12300]: [smux_accept] accepted fd 12 from 127.0.0.1:36255
|
||||
snmpd[12300]: accepted smux peer: \\
|
||||
oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, frr-0.96.5
|
||||
|
||||
# snmpwalk -c public -v1 localhost .1.3.6.1.2.1.14.1.1
|
||||
OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109
|
||||
|
||||
|
||||
Be warned that the current version (5.1.1) of the Net-SNMP daemon writes a line
|
||||
for every SNMP connect to the syslog which can lead to enormous log file sizes.
|
||||
If that is a problem you should consider to patch snmpd and comment out the
|
||||
troublesome `snmp_log()` line in the function `netsnmp_agent_check_packet()` in
|
||||
`agent/snmp_agent.c`.
|
||||
|
||||
MIB and command reference
|
||||
=========================
|
||||
|
||||
The following OID numbers are used for the interprocess communication of snmpd and
|
||||
the FRR daemons with SMUX only.::
|
||||
|
||||
. (OIDs below .iso.org.dod.internet.private.enterprises)
|
||||
zebra .1.3.6.1.4.1.3317.1.2.1 .gnome.gnomeProducts.zebra.zserv
|
||||
bgpd .1.3.6.1.4.1.3317.1.2.2 .gnome.gnomeProducts.zebra.bgpd
|
||||
ripd .1.3.6.1.4.1.3317.1.2.3 .gnome.gnomeProducts.zebra.ripd
|
||||
ospfd .1.3.6.1.4.1.3317.1.2.5 .gnome.gnomeProducts.zebra.ospfd
|
||||
ospf6d .1.3.6.1.4.1.3317.1.2.6 .gnome.gnomeProducts.zebra.ospf6d
|
||||
|
||||
|
||||
Sadly, SNMP has not been implemented in all daemons yet. The following
|
||||
OID numbers are used for querying the SNMP daemon by a client:::
|
||||
|
||||
zebra .1.3.6.1.2.1.4.24 .iso.org.dot.internet.mgmt.mib-2.ip.ipForward
|
||||
ospfd .1.3.6.1.2.1.14 .iso.org.dot.internet.mgmt.mib-2.ospf
|
||||
bgpd .1.3.6.1.2.1.15 .iso.org.dot.internet.mgmt.mib-2.bgp
|
||||
ripd .1.3.6.1.2.1.23 .iso.org.dot.internet.mgmt.mib-2.rip2
|
||||
ospf6d .1.3.6.1.3.102 .iso.org.dod.internet.experimental.ospfv3
|
||||
|
||||
|
||||
The following syntax is understood by the FRR daemons for configuring SNMP
|
||||
using SMUX:
|
||||
|
||||
.. index:: smux peer OID
|
||||
.. clicmd:: smux peer OID
|
||||
.. index:: no smux peer OID
|
||||
.. clicmd:: no smux peer OID
|
||||
.. index:: smux peer OID PASSWORD
|
||||
.. clicmd:: smux peer OID PASSWORD
|
||||
.. index:: no smux peer OID PASSWORD
|
||||
.. clicmd:: no smux peer OID PASSWORD
|
||||
|
||||
Here is the syntax for using AgentX:
|
||||
|
||||
.. index:: agentx
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "isisd/isis_constants.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_network.h"
|
||||
#include "isisd/isis_pdu.h"
|
||||
|
||||
#include "privs.h"
|
||||
|
||||
|
@ -536,7 +536,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
|
||||
*stream = stream_new(stream_size);
|
||||
} else {
|
||||
if (STREAM_SIZE(*stream) != stream_size)
|
||||
stream_resize(*stream, stream_size);
|
||||
stream_resize_inplace(stream, stream_size);
|
||||
stream_reset(*stream);
|
||||
}
|
||||
}
|
||||
|
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)
|
||||
return BUFFER_EMPTY;
|
||||
|
||||
if (height < 1) {
|
||||
zlog_warn(
|
||||
"%s called with non-positive window height %d, forcing to 1",
|
||||
__func__, height);
|
||||
if (height < 1)
|
||||
height = 1;
|
||||
} else if (height >= 2)
|
||||
else if (height >= 2)
|
||||
height--;
|
||||
if (width < 1) {
|
||||
zlog_warn(
|
||||
"%s called with non-positive window width %d, forcing to 1",
|
||||
__func__, width);
|
||||
if (width < 1)
|
||||
width = 1;
|
||||
}
|
||||
|
||||
/* For erase and more data add two to b's buffer_data count.*/
|
||||
if (b->head->next == NULL) {
|
||||
@ -334,11 +327,6 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
|
||||
{
|
||||
iov_alloc *= 2;
|
||||
if (iov != small_iov) {
|
||||
zlog_warn(
|
||||
"%s: growing iov array to %d; "
|
||||
"width %d, height %d, size %lu",
|
||||
__func__, iov_alloc, width, height,
|
||||
(unsigned long)b->size);
|
||||
iov = XREALLOC(MTYPE_TMP, iov,
|
||||
iov_alloc * sizeof(*iov));
|
||||
} else {
|
||||
|
@ -24,6 +24,9 @@
|
||||
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
|
||||
# define _RET_NONNULL , returns_nonnull
|
||||
#endif
|
||||
#if __has_attribute(fallthrough)
|
||||
# define _FALLTHROUGH __attribute__((fallthrough));
|
||||
#endif
|
||||
# define _CONSTRUCTOR(x) constructor(x)
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||
@ -34,6 +37,9 @@
|
||||
# define _DESTRUCTOR(x) destructor(x)
|
||||
# define _ALLOC_SIZE(x) alloc_size(x)
|
||||
#endif
|
||||
#if __GNUC__ >= 7
|
||||
# define _FALLTHROUGH __attribute__((fallthrough));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
@ -55,6 +61,9 @@
|
||||
#ifndef _ALLOC_SIZE
|
||||
# define _ALLOC_SIZE(x)
|
||||
#endif
|
||||
#ifndef _FALLTHROUGH
|
||||
#define _FALLTHROUGH
|
||||
#endif
|
||||
|
||||
/*
|
||||
* for warnings on macros, put in the macro content like this:
|
||||
|
@ -107,7 +107,7 @@ struct log_ref *log_ref_get(uint32_t code)
|
||||
void log_ref_display(struct vty *vty, uint32_t code, bool json)
|
||||
{
|
||||
struct log_ref *ref;
|
||||
struct json_object *top, *obj;
|
||||
struct json_object *top = NULL, *obj = NULL;
|
||||
struct list *errlist;
|
||||
struct listnode *ln;
|
||||
|
||||
@ -146,7 +146,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
|
||||
char ubuf[256];
|
||||
|
||||
snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
|
||||
code, ref->title);
|
||||
ref->code, ref->title);
|
||||
memset(ubuf, '=', strlen(pbuf));
|
||||
ubuf[sizeof(ubuf) - 1] = '\0';
|
||||
|
||||
|
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
|
||||
* then create the new interface
|
||||
*/
|
||||
if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id))
|
||||
if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(
|
||||
vrf_lookup_by_id(vrf_id)))
|
||||
return if_create(name, vrf_id);
|
||||
/* If it came from the kernel
|
||||
* or by way of zclient, believe it and update
|
||||
@ -471,6 +472,14 @@ int if_is_vrf(struct interface *ifp)
|
||||
return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
|
||||
}
|
||||
|
||||
bool if_is_loopback_or_vrf(struct interface *ifp)
|
||||
{
|
||||
if (if_is_loopback(ifp) || if_is_vrf(ifp))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Does this interface support broadcast ? */
|
||||
int if_is_broadcast(struct interface *ifp)
|
||||
{
|
||||
@ -1140,7 +1149,7 @@ const char *if_link_type_str(enum zebra_link_type llt)
|
||||
llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
|
||||
llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
|
||||
default:
|
||||
zlog_warn("Unknown value %d", llt);
|
||||
flog_err(LIB_ERR_DEVELOPMENT, "Unknown value %d", llt);
|
||||
return "Unknown type!";
|
||||
#undef llts
|
||||
}
|
||||
|
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_loopback(struct interface *);
|
||||
extern int if_is_vrf(struct interface *ifp);
|
||||
extern bool if_is_loopback_or_vrf(struct interface *ifp);
|
||||
extern int if_is_broadcast(struct interface *);
|
||||
extern int if_is_pointopoint(struct interface *);
|
||||
extern int if_is_multicast(struct interface *);
|
||||
|
@ -868,11 +868,16 @@ int zlog_rotate(void)
|
||||
save_errno = errno;
|
||||
umask(oldumask);
|
||||
if (zl->fp == NULL) {
|
||||
|
||||
pthread_mutex_unlock(&loglock);
|
||||
|
||||
flog_err_sys(
|
||||
LIB_ERR_SYSTEM_CALL,
|
||||
"Log rotate failed: cannot open file %s for append: %s",
|
||||
zl->filename, safe_strerror(save_errno));
|
||||
ret = -1;
|
||||
|
||||
pthread_mutex_lock(&loglock);
|
||||
} else {
|
||||
logfile_fd = fileno(zl->fp);
|
||||
zl->maxlvl[ZLOG_DEST_FILE] = level;
|
||||
@ -903,10 +908,6 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_ROUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_ROUTE_DELETE),
|
||||
DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER),
|
||||
DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
|
||||
DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_IPV6_ROUTE_DELETE),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE),
|
||||
DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
|
||||
|
@ -87,7 +87,7 @@ extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
|
||||
|
||||
/* For logs which have error codes associated with them */
|
||||
#define flog_err(ferr_id, format, ...) \
|
||||
zlog_err("[EC %d] " format, ferr_id, ##__VA_ARGS__)
|
||||
zlog_err("[EC %"PRIu32"] " format, ferr_id, ##__VA_ARGS__)
|
||||
#define flog_err_sys(ferr_id, format, ...) \
|
||||
flog_err(ferr_id, format, ##__VA_ARGS__)
|
||||
|
||||
|
1416
lib/smux.c
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)
|
||||
{
|
||||
#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
|
||||
/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's
|
||||
* version of the Quagga patch (based on work by Rick Payne, and Bruce
|
||||
* Simpson)
|
||||
*/
|
||||
#define TCP_MD5_AUTH 13
|
||||
#define TCP_MD5_AUTH_ADD 1
|
||||
#define TCP_MD5_AUTH_DEL 2
|
||||
struct tcp_rfc2385_cmd {
|
||||
uint8_t command; /* Command - Add/Delete */
|
||||
uint32_t address; /* IPV4 address associated */
|
||||
uint8_t keylen; /* MD5 Key len (do NOT assume 0 terminated
|
||||
ascii) */
|
||||
void *key; /* MD5 Key */
|
||||
} cmd;
|
||||
struct in_addr *addr = &su->sin.sin_addr;
|
||||
|
||||
cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL);
|
||||
cmd.address = addr->s_addr;
|
||||
cmd.keylen = (password != NULL ? strlen(password) : 0);
|
||||
cmd.key = password;
|
||||
|
||||
return setsockopt(sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
|
||||
|
||||
#elif HAVE_DECL_TCP_MD5SIG
|
||||
#if HAVE_DECL_TCP_MD5SIG
|
||||
int ret;
|
||||
#ifndef GNU_LINUX
|
||||
/*
|
||||
|
@ -143,7 +143,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread)
|
||||
|
||||
long spf_backoff_schedule(struct spf_backoff *backoff)
|
||||
{
|
||||
long rv;
|
||||
long rv = 0;
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
@ -176,9 +176,6 @@ long spf_backoff_schedule(struct spf_backoff *backoff)
|
||||
else
|
||||
rv = backoff->long_delay;
|
||||
break;
|
||||
default:
|
||||
zlog_warn("SPF Back-off(%s) in unknown state", backoff->name);
|
||||
rv = backoff->init_delay;
|
||||
}
|
||||
|
||||
backoff_debug(
|
||||
|
41
lib/stream.c
41
lib/stream.c
@ -28,9 +28,9 @@
|
||||
#include "network.h"
|
||||
#include "prefix.h"
|
||||
#include "log.h"
|
||||
#include "lib_errors.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
|
||||
DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data")
|
||||
DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
|
||||
|
||||
/* Tests whether a position is valid */
|
||||
@ -100,9 +100,7 @@ struct stream *stream_new(size_t size)
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream));
|
||||
|
||||
s->data = XMALLOC(MTYPE_STREAM_DATA, size);
|
||||
s = XMALLOC(MTYPE_STREAM, sizeof(struct stream) + size);
|
||||
|
||||
s->getp = s->endp = 0;
|
||||
s->next = NULL;
|
||||
@ -116,7 +114,6 @@ void stream_free(struct stream *s)
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
XFREE(MTYPE_STREAM_DATA, s->data);
|
||||
XFREE(MTYPE_STREAM, s);
|
||||
}
|
||||
|
||||
@ -166,27 +163,33 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2,
|
||||
return new;
|
||||
}
|
||||
|
||||
size_t stream_resize(struct stream *s, size_t newsize)
|
||||
size_t stream_resize_inplace(struct stream **sptr, size_t newsize)
|
||||
{
|
||||
uint8_t *newdata;
|
||||
STREAM_VERIFY_SANE(s);
|
||||
struct stream *orig = *sptr;
|
||||
|
||||
newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize);
|
||||
STREAM_VERIFY_SANE(orig);
|
||||
|
||||
if (newdata == NULL)
|
||||
return s->size;
|
||||
orig = XREALLOC(MTYPE_STREAM, orig, sizeof(struct stream) + newsize);
|
||||
|
||||
s->data = newdata;
|
||||
s->size = newsize;
|
||||
orig->size = newsize;
|
||||
|
||||
if (s->endp > s->size)
|
||||
s->endp = s->size;
|
||||
if (s->getp > s->endp)
|
||||
s->getp = s->endp;
|
||||
if (orig->endp > orig->size)
|
||||
orig->endp = orig->size;
|
||||
if (orig->getp > orig->endp)
|
||||
orig->getp = orig->endp;
|
||||
|
||||
STREAM_VERIFY_SANE(s);
|
||||
STREAM_VERIFY_SANE(orig);
|
||||
|
||||
return s->size;
|
||||
*sptr = orig;
|
||||
return orig->size;
|
||||
}
|
||||
|
||||
size_t __attribute__((deprecated))stream_resize_orig(struct stream *s,
|
||||
size_t newsize)
|
||||
{
|
||||
assert("stream_resize: Switch code to use stream_resize_inplace" == NULL);
|
||||
|
||||
return stream_resize_inplace(&s, newsize);
|
||||
}
|
||||
|
||||
size_t stream_get_getp(struct stream *s)
|
||||
|
20
lib/stream.h
20
lib/stream.h
@ -98,14 +98,15 @@
|
||||
struct stream {
|
||||
struct stream *next;
|
||||
|
||||
/* Remainder is ***private*** to stream
|
||||
/*
|
||||
* Remainder is ***private*** to stream
|
||||
* direct access is frowned upon!
|
||||
* Use the appropriate functions/macros
|
||||
*/
|
||||
size_t getp; /* next get position */
|
||||
size_t endp; /* last valid data position */
|
||||
size_t size; /* size of data segment */
|
||||
unsigned char *data; /* data pointer */
|
||||
size_t getp; /* next get position */
|
||||
size_t endp; /* last valid data position */
|
||||
size_t size; /* size of data segment */
|
||||
unsigned char data[0]; /* data pointer */
|
||||
};
|
||||
|
||||
/* First in first out queue structure. */
|
||||
@ -154,7 +155,14 @@ extern struct stream *stream_new(size_t);
|
||||
extern void stream_free(struct stream *);
|
||||
extern struct stream *stream_copy(struct stream *, struct stream *src);
|
||||
extern struct stream *stream_dup(struct stream *);
|
||||
extern size_t stream_resize(struct stream *, size_t);
|
||||
|
||||
#if CONFDATE > 20190821
|
||||
CPP_NOTICE("lib: time to remove stream_resize_orig")
|
||||
#endif
|
||||
extern size_t stream_resize_orig(struct stream *s, size_t newsize);
|
||||
#define stream_resize stream_resize_orig
|
||||
extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
|
||||
|
||||
extern size_t stream_get_getp(struct stream *);
|
||||
extern size_t stream_get_endp(struct stream *);
|
||||
extern size_t stream_get_size(struct stream *);
|
||||
|
@ -150,7 +150,6 @@ pkginclude_HEADERS += \
|
||||
lib/sha256.h \
|
||||
lib/sigevent.h \
|
||||
lib/skiplist.h \
|
||||
lib/smux.h \
|
||||
lib/sockopt.h \
|
||||
lib/sockunion.h \
|
||||
lib/spf_backoff.h \
|
||||
@ -199,7 +198,6 @@ lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
|
||||
lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
|
||||
lib_libfrrsnmp_la_SOURCES = \
|
||||
lib/agentx.c \
|
||||
lib/smux.c \
|
||||
lib/snmp.c \
|
||||
# end
|
||||
|
||||
|
@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node)
|
||||
}
|
||||
|
||||
/* Unlock node. */
|
||||
static inline struct route_node *route_unlock_node(struct route_node *node)
|
||||
static inline void route_unlock_node(struct route_node *node)
|
||||
{
|
||||
assert(node->lock > 0);
|
||||
(*(unsigned *)&node->lock)--;
|
||||
|
||||
if (node->lock == 0) {
|
||||
if (node->lock == 0)
|
||||
route_node_delete(node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
|
45
lib/thread.c
45
lib/thread.c
@ -36,6 +36,7 @@
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
|
||||
DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master")
|
||||
DEFINE_MTYPE_STATIC(LIB, THREAD_POLL, "Thread Poll Info")
|
||||
DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@ -423,19 +424,11 @@ struct thread_master *thread_master_create(const char *name)
|
||||
/* Initialize I/O task data structures */
|
||||
getrlimit(RLIMIT_NOFILE, &limit);
|
||||
rv->fd_limit = (int)limit.rlim_cur;
|
||||
rv->read =
|
||||
XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
|
||||
if (rv->read == NULL) {
|
||||
XFREE(MTYPE_THREAD_MASTER, rv);
|
||||
return NULL;
|
||||
}
|
||||
rv->write =
|
||||
XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
|
||||
if (rv->write == NULL) {
|
||||
XFREE(MTYPE_THREAD, rv->read);
|
||||
XFREE(MTYPE_THREAD_MASTER, rv);
|
||||
return NULL;
|
||||
}
|
||||
rv->read = XCALLOC(MTYPE_THREAD_POLL,
|
||||
sizeof(struct thread *) * rv->fd_limit);
|
||||
|
||||
rv->write = XCALLOC(MTYPE_THREAD_POLL,
|
||||
sizeof(struct thread *) * rv->fd_limit);
|
||||
|
||||
rv->cpu_record = hash_create_size(
|
||||
8, (unsigned int (*)(void *))cpu_record_hash_key,
|
||||
@ -539,17 +532,23 @@ static struct thread *thread_trim_head(struct thread_list *list)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define THREAD_UNUSED_DEPTH 10
|
||||
|
||||
/* Move thread to unuse list. */
|
||||
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
||||
{
|
||||
assert(m != NULL && thread != NULL);
|
||||
assert(thread->next == NULL);
|
||||
assert(thread->prev == NULL);
|
||||
thread->ref = NULL;
|
||||
|
||||
thread->type = THREAD_UNUSED;
|
||||
thread->hist->total_active--;
|
||||
thread_list_add(&m->unuse, thread);
|
||||
memset(thread, 0, sizeof(struct thread));
|
||||
thread->type = THREAD_UNUSED;
|
||||
|
||||
if (m->unuse.count < THREAD_UNUSED_DEPTH)
|
||||
thread_list_add(&m->unuse, thread);
|
||||
else
|
||||
XFREE(MTYPE_THREAD, thread);
|
||||
}
|
||||
|
||||
/* Free all unused thread. */
|
||||
@ -580,7 +579,7 @@ static void thread_array_free(struct thread_master *m,
|
||||
m->alloc--;
|
||||
}
|
||||
}
|
||||
XFREE(MTYPE_THREAD, thread_array);
|
||||
XFREE(MTYPE_THREAD_POLL, thread_array);
|
||||
}
|
||||
|
||||
static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
|
||||
@ -1182,17 +1181,19 @@ void thread_cancel_event(struct thread_master *master, void *arg)
|
||||
*/
|
||||
void thread_cancel(struct thread *thread)
|
||||
{
|
||||
assert(thread->master->owner == pthread_self());
|
||||
struct thread_master *master = thread->master;
|
||||
|
||||
pthread_mutex_lock(&thread->master->mtx);
|
||||
assert(master->owner == pthread_self());
|
||||
|
||||
pthread_mutex_lock(&master->mtx);
|
||||
{
|
||||
struct cancel_req *cr =
|
||||
XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
|
||||
cr->thread = thread;
|
||||
listnode_add(thread->master->cancel_req, cr);
|
||||
do_thread_cancel(thread->master);
|
||||
listnode_add(master->cancel_req, cr);
|
||||
do_thread_cancel(master);
|
||||
}
|
||||
pthread_mutex_unlock(&thread->master->mtx);
|
||||
pthread_mutex_unlock(&master->mtx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
122
lib/vrf.c
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.
|
||||
*/
|
||||
|
||||
#define VRF_BITMAP_NUM_OF_GROUPS 1024
|
||||
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
|
||||
#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
|
||||
(VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
|
||||
|
||||
#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
|
||||
#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
|
||||
|
||||
#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT)
|
||||
#define VRF_BITMAP_FLAG(_bit_offset) \
|
||||
(((uint8_t)1) << ((_bit_offset) % CHAR_BIT))
|
||||
|
||||
struct vrf_bitmap {
|
||||
uint8_t *groups[VRF_BITMAP_NUM_OF_GROUPS];
|
||||
struct vrf_bit_set {
|
||||
vrf_id_t vrf_id;
|
||||
bool set;
|
||||
};
|
||||
|
||||
static unsigned int vrf_hash_bitmap_key(void *data)
|
||||
{
|
||||
struct vrf_bit_set *bit = data;
|
||||
|
||||
return bit->vrf_id;
|
||||
}
|
||||
|
||||
static int vrf_hash_bitmap_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct vrf_bit_set *bit1 = a;
|
||||
const struct vrf_bit_set *bit2 = b;
|
||||
|
||||
return bit1->vrf_id == bit2->vrf_id;
|
||||
}
|
||||
|
||||
static void *vrf_hash_bitmap_alloc(void *data)
|
||||
{
|
||||
struct vrf_bit_set *copy = data;
|
||||
struct vrf_bit_set *bit;
|
||||
|
||||
bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
|
||||
bit->vrf_id = copy->vrf_id;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
static void vrf_hash_bitmap_free(void *data)
|
||||
{
|
||||
struct vrf_bit_set *bit = data;
|
||||
|
||||
XFREE(MTYPE_VRF_BITMAP, bit);
|
||||
}
|
||||
|
||||
vrf_bitmap_t vrf_bitmap_init(void)
|
||||
{
|
||||
return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
|
||||
sizeof(struct vrf_bitmap));
|
||||
return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
|
||||
"VRF BIT HASH");
|
||||
}
|
||||
|
||||
void vrf_bitmap_free(vrf_bitmap_t bmap)
|
||||
{
|
||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
||||
int i;
|
||||
struct hash *vrf_hash = bmap;
|
||||
|
||||
if (bmap == VRF_BITMAP_NULL)
|
||||
if (vrf_hash == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
|
||||
if (bm->groups[i])
|
||||
XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
|
||||
|
||||
XFREE(MTYPE_VRF_BITMAP, bm);
|
||||
hash_clean(vrf_hash, vrf_hash_bitmap_free);
|
||||
hash_free(vrf_hash);
|
||||
}
|
||||
|
||||
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||
{
|
||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
||||
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||
struct hash *vrf_hash = bmap;
|
||||
struct vrf_bit_set *bit;
|
||||
|
||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
|
||||
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||
return;
|
||||
|
||||
if (bm->groups[group] == NULL)
|
||||
bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
|
||||
VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
|
||||
|
||||
SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
||||
VRF_BITMAP_FLAG(offset));
|
||||
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
||||
bit->set = true;
|
||||
}
|
||||
|
||||
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||
{
|
||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
||||
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||
struct hash *vrf_hash = bmap;
|
||||
struct vrf_bit_set *bit;
|
||||
|
||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|
||||
|| bm->groups[group] == NULL)
|
||||
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||
return;
|
||||
|
||||
UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
||||
VRF_BITMAP_FLAG(offset));
|
||||
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
||||
bit->set = false;
|
||||
}
|
||||
|
||||
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
||||
{
|
||||
struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
|
||||
uint8_t group = VRF_BITMAP_GROUP(vrf_id);
|
||||
uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
|
||||
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
||||
struct hash *vrf_hash = bmap;
|
||||
struct vrf_bit_set *bit;
|
||||
|
||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
|
||||
|| bm->groups[group] == NULL)
|
||||
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
|
||||
VRF_BITMAP_FLAG(offset))
|
||||
? 1
|
||||
: 0;
|
||||
bit = hash_lookup(vrf_hash, &lookup);
|
||||
if (bit)
|
||||
return bit->set;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vrf_autocomplete(vector comps, struct cmd_token *token)
|
||||
@ -682,10 +694,8 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
|
||||
int vrf_is_mapped_on_netns(struct vrf *vrf)
|
||||
{
|
||||
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
|
||||
|
||||
if (!vrf || vrf->data.l.netns_name[0] == '\0')
|
||||
return 0;
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
@ -887,7 +897,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
|
||||
|
||||
if (fd < 0 || name == NULL)
|
||||
return fd;
|
||||
if (vrf_is_mapped_on_netns(vrf_id))
|
||||
if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id)))
|
||||
return fd;
|
||||
#ifdef SO_BINDTODEVICE
|
||||
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
|
||||
|
@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void);
|
||||
#define VRF_DEFAULT vrf_get_default_id()
|
||||
|
||||
/* VRF is mapped on netns or not ? */
|
||||
int vrf_is_mapped_on_netns(vrf_id_t vrf_id);
|
||||
int vrf_is_mapped_on_netns(struct vrf *vrf);
|
||||
|
||||
/* VRF switch from NETNS */
|
||||
extern int vrf_switch_to_netns(vrf_id_t vrf_id);
|
||||
|
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
|
||||
* a message to zebra server for a route that needs to be
|
||||
* added/deleted to the kernel. Info about the route is specified
|
||||
* by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
|
||||
* by the caller in a struct zapi_route. zapi_route_encode() then writes
|
||||
* the info down the zclient socket using the stream_* functions.
|
||||
*
|
||||
* The corresponding read ("xdr_decode") function on the server
|
||||
* side is zread_ipv4_add()/zread_ipv4_delete().
|
||||
* side is zapi_route_decode().
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@ -707,21 +707,16 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
|
||||
* is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole
|
||||
* nexthop.
|
||||
*
|
||||
* The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
|
||||
* infrastructure was built around the traditional (32-bit "gate OR
|
||||
* ifindex") nexthop data unit. A special encoding can be used to feed
|
||||
* onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
|
||||
* using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
|
||||
* fields as follows:
|
||||
* The original struct zapi_route_*() infrastructure was built around
|
||||
* the traditional (32-bit "gate OR ifindex") nexthop data unit.
|
||||
* A special encoding can be used to feed onlink (64-bit "gate AND ifindex")
|
||||
* nexthops into zapi_route_encode() using the same zapi_route structure.
|
||||
* This is done by setting zapi_route fields as follows:
|
||||
* - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
|
||||
* - .nexthop_num == .ifindex_num
|
||||
* - .nexthop and .ifindex are filled with gate and ifindex parts of
|
||||
* each compound nexthop, both in the same order
|
||||
*
|
||||
* zapi_ipv4_route() will produce two nexthop data units for each such
|
||||
* interleaved 64-bit nexthop. On the zserv side of the socket it will be
|
||||
* mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure.
|
||||
*
|
||||
* If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
|
||||
* byte value.
|
||||
*
|
||||
@ -734,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
|
||||
*
|
||||
* XXX: No attention paid to alignment.
|
||||
*/
|
||||
int zapi_ipv4_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv4 *p,
|
||||
struct zapi_ipv4 *api)
|
||||
{
|
||||
int i;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
|
||||
/* Reset stream. */
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
|
||||
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
/* We expect prefixes installed with labels and the number to
|
||||
* match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert(api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header(s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
stream_putc(s, api->type);
|
||||
stream_putw(s, api->instance);
|
||||
stream_putl(s, api->flags);
|
||||
stream_putc(s, api->message);
|
||||
stream_putw(s, api->safi);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE(p->prefixlen);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_write(s, (uint8_t *)&p->prefix, psize);
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
stream_putc(s, api->nexthop_num + api->ifindex_num);
|
||||
|
||||
for (i = 0; i < api->nexthop_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IPV4);
|
||||
stream_put_in_addr(s, api->nexthop[i]);
|
||||
/* For labeled-unicast, each nexthop is followed by
|
||||
* label. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl(s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
|
||||
stream_putl(s, api->ifindex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
|
||||
stream_putc(s, api->distance);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
|
||||
stream_putl(s, api->metric);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
|
||||
stream_putl(s, api->tag);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
|
||||
stream_putl(s, api->mtu);
|
||||
|
||||
/* Put length at the first point of the stream. */
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int zapi_ipv4_route_ipv6_nexthop(uint8_t cmd, struct zclient *zclient,
|
||||
struct prefix_ipv4 *p, struct zapi_ipv6 *api)
|
||||
{
|
||||
int i;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
|
||||
/* Reset stream. */
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
|
||||
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
/* We expect prefixes installed with labels and the number to
|
||||
* match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert(api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header(s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
stream_putc(s, api->type);
|
||||
stream_putw(s, api->instance);
|
||||
stream_putl(s, api->flags);
|
||||
stream_putc(s, api->message);
|
||||
stream_putw(s, api->safi);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE(p->prefixlen);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_write(s, (uint8_t *)&p->prefix, psize);
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
stream_putc(s, api->nexthop_num + api->ifindex_num);
|
||||
|
||||
for (i = 0; i < api->nexthop_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IPV6);
|
||||
stream_write(s, (uint8_t *)api->nexthop[i], 16);
|
||||
/* For labeled-unicast, each nexthop is followed by
|
||||
* label. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl(s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
|
||||
stream_putl(s, api->ifindex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
|
||||
stream_putc(s, api->distance);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
|
||||
stream_putl(s, api->metric);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
|
||||
stream_putl(s, api->tag);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
|
||||
stream_putl(s, api->mtu);
|
||||
|
||||
/* Put length at the first point of the stream. */
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv6 *p,
|
||||
struct prefix_ipv6 *src_p, struct zapi_ipv6 *api)
|
||||
{
|
||||
int i;
|
||||
int psize;
|
||||
struct stream *s;
|
||||
|
||||
/* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL
|
||||
*/
|
||||
assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p);
|
||||
|
||||
/* Reset stream. */
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
|
||||
/* Some checks for labeled-unicast. The current expectation is that each
|
||||
* nexthop is accompanied by a label in the case of labeled-unicast.
|
||||
*/
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
|
||||
&& CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
/* We expect prefixes installed with labels and the number to
|
||||
* match
|
||||
* the number of nexthops.
|
||||
*/
|
||||
assert(api->label_num == api->nexthop_num);
|
||||
}
|
||||
|
||||
zclient_create_header(s, cmd, api->vrf_id);
|
||||
|
||||
/* Put type and nexthop. */
|
||||
stream_putc(s, api->type);
|
||||
stream_putw(s, api->instance);
|
||||
stream_putl(s, api->flags);
|
||||
stream_putc(s, api->message);
|
||||
stream_putw(s, api->safi);
|
||||
|
||||
/* Put prefix information. */
|
||||
psize = PSIZE(p->prefixlen);
|
||||
stream_putc(s, p->prefixlen);
|
||||
stream_write(s, (uint8_t *)&p->prefix, psize);
|
||||
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
|
||||
psize = PSIZE(src_p->prefixlen);
|
||||
stream_putc(s, src_p->prefixlen);
|
||||
stream_write(s, (uint8_t *)&src_p->prefix, psize);
|
||||
}
|
||||
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
stream_putc(s, api->nexthop_num + api->ifindex_num);
|
||||
|
||||
for (i = 0; i < api->nexthop_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IPV6);
|
||||
stream_write(s, (uint8_t *)api->nexthop[i], 16);
|
||||
/* For labeled-unicast, each nexthop is followed by
|
||||
* label. */
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
|
||||
stream_putl(s, api->label[i]);
|
||||
}
|
||||
for (i = 0; i < api->ifindex_num; i++) {
|
||||
stream_putc(s, NEXTHOP_TYPE_IFINDEX);
|
||||
stream_putl(s, api->ifindex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
|
||||
stream_putc(s, api->distance);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
|
||||
stream_putl(s, api->metric);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
|
||||
stream_putl(s, api->tag);
|
||||
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
|
||||
stream_putl(s, api->mtu);
|
||||
|
||||
/* Put length at the first point of the stream. */
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
int zclient_route_send(uint8_t cmd, struct zclient *zclient,
|
||||
struct zapi_route *api)
|
||||
{
|
||||
|
@ -73,10 +73,6 @@ typedef enum {
|
||||
ZEBRA_ROUTE_ADD,
|
||||
ZEBRA_ROUTE_DELETE,
|
||||
ZEBRA_ROUTE_NOTIFY_OWNER,
|
||||
ZEBRA_IPV4_ROUTE_ADD,
|
||||
ZEBRA_IPV4_ROUTE_DELETE,
|
||||
ZEBRA_IPV6_ROUTE_ADD,
|
||||
ZEBRA_IPV6_ROUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_ADD,
|
||||
ZEBRA_REDISTRIBUTE_DELETE,
|
||||
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
|
||||
@ -286,7 +282,7 @@ struct zclient {
|
||||
*/
|
||||
#define ZAPI_MESSAGE_TABLEID 0x80
|
||||
|
||||
#define ZSERV_VERSION 5
|
||||
#define ZSERV_VERSION 6
|
||||
/* Zserv protocol message header */
|
||||
struct zmsghdr {
|
||||
uint16_t length;
|
||||
@ -353,37 +349,6 @@ struct zapi_route {
|
||||
uint32_t tableid;
|
||||
};
|
||||
|
||||
/* Zebra IPv4 route message API. */
|
||||
struct zapi_ipv4 {
|
||||
uint8_t type;
|
||||
unsigned short instance;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
uint8_t message;
|
||||
|
||||
safi_t safi;
|
||||
|
||||
uint8_t nexthop_num;
|
||||
struct in_addr **nexthop;
|
||||
|
||||
uint8_t ifindex_num;
|
||||
ifindex_t *ifindex;
|
||||
|
||||
uint8_t label_num;
|
||||
unsigned int *label;
|
||||
|
||||
uint8_t distance;
|
||||
|
||||
uint32_t metric;
|
||||
|
||||
route_tag_t tag;
|
||||
|
||||
uint32_t mtu;
|
||||
|
||||
vrf_id_t vrf_id;
|
||||
};
|
||||
|
||||
struct zapi_pw {
|
||||
char ifname[IF_NAMESIZE];
|
||||
ifindex_t ifindex;
|
||||
@ -600,15 +565,6 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
|
||||
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
|
||||
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
|
||||
|
||||
/* clang-format off */
|
||||
#if CONFDATE > 20180823
|
||||
CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
extern int zapi_ipv4_route(uint8_t, struct zclient *, struct prefix_ipv4 *,
|
||||
struct zapi_ipv4 *) __attribute__((deprecated));
|
||||
|
||||
extern struct interface *zebra_interface_link_params_read(struct stream *);
|
||||
extern size_t zebra_interface_link_params_write(struct stream *,
|
||||
struct interface *);
|
||||
@ -635,45 +591,6 @@ extern void zebra_read_pw_status_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id,
|
||||
struct zapi_pw_status *pw);
|
||||
|
||||
/* IPv6 prefix add and delete function prototype. */
|
||||
|
||||
struct zapi_ipv6 {
|
||||
uint8_t type;
|
||||
unsigned short instance;
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
uint8_t message;
|
||||
|
||||
safi_t safi;
|
||||
|
||||
uint8_t nexthop_num;
|
||||
struct in6_addr **nexthop;
|
||||
|
||||
uint8_t ifindex_num;
|
||||
ifindex_t *ifindex;
|
||||
|
||||
uint8_t label_num;
|
||||
unsigned int *label;
|
||||
|
||||
uint8_t distance;
|
||||
|
||||
uint32_t metric;
|
||||
|
||||
route_tag_t tag;
|
||||
|
||||
uint32_t mtu;
|
||||
|
||||
vrf_id_t vrf_id;
|
||||
};
|
||||
|
||||
extern int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient,
|
||||
struct prefix_ipv6 *p, struct prefix_ipv6 *src_p,
|
||||
struct zapi_ipv6 *api) __attribute__((deprecated));
|
||||
extern int zapi_ipv4_route_ipv6_nexthop(uint8_t, struct zclient *,
|
||||
struct prefix_ipv4 *,
|
||||
struct zapi_ipv6 *)
|
||||
__attribute__((deprecated));
|
||||
extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *);
|
||||
extern int zclient_send_rnh(struct zclient *zclient, int command,
|
||||
struct prefix *p, bool exact_match,
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "ospfd/ospf_lsdb.h"
|
||||
#include "ospfd/ospf_neighbor.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_api.h"
|
||||
|
||||
|
@ -1425,19 +1425,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
|
||||
newlsa->length = htons(length);
|
||||
|
||||
/* Create OSPF LSA. */
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
|
||||
zlog_warn(
|
||||
"ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
new->area = area;
|
||||
new->oi = oi;
|
||||
|
@ -73,26 +73,6 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
|
||||
p->prefixlen);
|
||||
}
|
||||
|
||||
/* Lookup external route. */
|
||||
struct ospf_route *ospf_external_route_lookup(struct ospf *ospf,
|
||||
struct prefix_ipv4 *p)
|
||||
{
|
||||
struct route_node *rn;
|
||||
|
||||
rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p);
|
||||
if (rn) {
|
||||
route_unlock_node(rn);
|
||||
if (rn->info)
|
||||
return rn->info;
|
||||
}
|
||||
|
||||
zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p->prefix),
|
||||
p->prefixlen);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Add an External info for AS-external-LSA. */
|
||||
struct external_info *ospf_external_info_new(uint8_t type,
|
||||
unsigned short instance)
|
||||
|
@ -68,8 +68,6 @@ extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
|
||||
extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
|
||||
unsigned short,
|
||||
struct prefix_ipv4 *);
|
||||
extern struct ospf_route *ospf_external_route_lookup(struct ospf *,
|
||||
struct prefix_ipv4 *);
|
||||
extern void ospf_asbr_status_update(struct ospf *, uint8_t);
|
||||
|
||||
extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
|
||||
|
@ -288,6 +288,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
|
||||
struct prefix_ipv4 asbr, p;
|
||||
struct route_node *rn;
|
||||
struct ospf_route *new, * or ;
|
||||
char buf1[INET_ADDRSTRLEN];
|
||||
int ret;
|
||||
|
||||
assert(lsa);
|
||||
@ -304,10 +305,14 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_DEBUG_OSPF(lsa, LSA))
|
||||
if (IS_DEBUG_OSPF(lsa, LSA)) {
|
||||
snprintf(buf1, INET_ADDRSTRLEN, "%s",
|
||||
inet_ntoa(al->header.adv_router));
|
||||
zlog_debug(
|
||||
"Route[External]: Calculate AS-external-LSA to %s/%d",
|
||||
inet_ntoa(al->header.id), ip_masklen(al->mask));
|
||||
"Route[External]: Calculate AS-external-LSA to %s/%d adv_router %s",
|
||||
inet_ntoa(al->header.id), ip_masklen(al->mask), buf1);
|
||||
}
|
||||
|
||||
/* (1) If the cost specified by the LSA is LSInfinity, or if the
|
||||
LSA's LS age is equal to MaxAge, then examine the next LSA. */
|
||||
if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) {
|
||||
@ -459,8 +464,9 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
|
||||
|
||||
if (!rn || (or = rn->info) == NULL) {
|
||||
if (IS_DEBUG_OSPF(lsa, LSA))
|
||||
zlog_debug("Route[External]: Adding a new route %s/%d",
|
||||
inet_ntoa(p.prefix), p.prefixlen);
|
||||
zlog_debug("Route[External]: Adding a new route %s/%d with paths %u",
|
||||
inet_ntoa(p.prefix), p.prefixlen,
|
||||
listcount(asbr_route->paths));
|
||||
|
||||
ospf_route_add(ospf->new_external_route, &p, new, asbr_route);
|
||||
|
||||
|
@ -977,20 +977,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create an OSPF LSA instance. */
|
||||
new = ospf_lsa_new();
|
||||
if (new == NULL) {
|
||||
zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
if (new->data == NULL) {
|
||||
zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
/* Segment Routing belongs only to default VRF */
|
||||
new->vrf_id = VRF_DEFAULT;
|
||||
@ -1056,20 +1043,7 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create an OSPF LSA instance. */
|
||||
new = ospf_lsa_new();
|
||||
if (new == NULL) {
|
||||
zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
if (new->data == NULL) {
|
||||
zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
/* Segment Routing belongs only to default VRF */
|
||||
new->vrf_id = VRF_DEFAULT;
|
||||
|
@ -810,8 +810,7 @@ struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah)
|
||||
{
|
||||
struct ospf_lsa *new;
|
||||
|
||||
new = ospf_lsa_new();
|
||||
new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE);
|
||||
new = ospf_lsa_new_and_data(OSPF_LSA_HEADER_SIZE);
|
||||
memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE);
|
||||
|
||||
return new;
|
||||
|
@ -167,6 +167,16 @@ struct ospf_lsa *ospf_lsa_new()
|
||||
return new;
|
||||
}
|
||||
|
||||
struct ospf_lsa *ospf_lsa_new_and_data(size_t size)
|
||||
{
|
||||
struct ospf_lsa *new;
|
||||
|
||||
new = ospf_lsa_new();
|
||||
new->data = ospf_lsa_data_new(size);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Duplicate OSPF LSA. */
|
||||
struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa)
|
||||
{
|
||||
@ -406,7 +416,7 @@ static uint16_t ospf_link_cost(struct ospf_interface *oi)
|
||||
}
|
||||
|
||||
/* Set a link information. */
|
||||
static char link_info_set(struct stream *s, struct in_addr id,
|
||||
static char link_info_set(struct stream **s, struct in_addr id,
|
||||
struct in_addr data, uint8_t type, uint8_t tos,
|
||||
uint16_t cost)
|
||||
{
|
||||
@ -415,11 +425,11 @@ static char link_info_set(struct stream *s, struct in_addr id,
|
||||
* more.
|
||||
* we try accomodate those here.
|
||||
*/
|
||||
if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) {
|
||||
if (STREAM_WRITEABLE(*s) < OSPF_ROUTER_LSA_LINK_SIZE) {
|
||||
size_t ret = OSPF_MAX_LSA_SIZE;
|
||||
|
||||
/* Can we enlarge the stream still? */
|
||||
if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) {
|
||||
if (STREAM_SIZE(*s) == OSPF_MAX_LSA_SIZE) {
|
||||
/* we futz the size here for simplicity, really we need
|
||||
* to account
|
||||
* for just:
|
||||
@ -431,30 +441,31 @@ static char link_info_set(struct stream *s, struct in_addr id,
|
||||
*
|
||||
* Simpler just to subtract OSPF_MAX_LSA_SIZE though.
|
||||
*/
|
||||
ret = stream_resize(
|
||||
ret = stream_resize_inplace(
|
||||
s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
|
||||
}
|
||||
|
||||
if (ret == OSPF_MAX_LSA_SIZE) {
|
||||
zlog_warn(
|
||||
"%s: Out of space in LSA stream, left %zd, size %zd",
|
||||
__func__, STREAM_WRITEABLE(s), STREAM_SIZE(s));
|
||||
__func__, STREAM_WRITEABLE(*s),
|
||||
STREAM_SIZE(*s));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* TOS based routing is not supported. */
|
||||
stream_put_ipv4(s, id.s_addr); /* Link ID. */
|
||||
stream_put_ipv4(s, data.s_addr); /* Link Data. */
|
||||
stream_putc(s, type); /* Link Type. */
|
||||
stream_putc(s, tos); /* TOS = 0. */
|
||||
stream_putw(s, cost); /* Link Cost. */
|
||||
stream_put_ipv4(*s, id.s_addr); /* Link ID. */
|
||||
stream_put_ipv4(*s, data.s_addr); /* Link Data. */
|
||||
stream_putc(*s, type); /* Link Type. */
|
||||
stream_putc(*s, tos); /* TOS = 0. */
|
||||
stream_putw(*s, cost); /* Link Cost. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Describe Point-to-Point link (Section 12.4.1.1). */
|
||||
static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
|
||||
static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
|
||||
{
|
||||
int links = 0;
|
||||
struct ospf_neighbor *nbr;
|
||||
@ -500,7 +511,7 @@ static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
|
||||
}
|
||||
|
||||
/* Describe Broadcast Link. */
|
||||
static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
|
||||
static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
|
||||
{
|
||||
struct ospf_neighbor *dr;
|
||||
struct in_addr id, mask;
|
||||
@ -546,7 +557,7 @@ static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
|
||||
}
|
||||
}
|
||||
|
||||
static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
|
||||
static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi)
|
||||
{
|
||||
struct in_addr id, mask;
|
||||
|
||||
@ -560,7 +571,8 @@ static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
|
||||
}
|
||||
|
||||
/* Describe Virtual Link. */
|
||||
static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
|
||||
static int lsa_link_virtuallink_set(struct stream **s,
|
||||
struct ospf_interface *oi)
|
||||
{
|
||||
struct ospf_neighbor *nbr;
|
||||
uint16_t cost = ospf_link_cost(oi);
|
||||
@ -583,7 +595,7 @@ static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
|
||||
12.4.1.4.*/
|
||||
/* from "edward rrr" <edward_rrr@hotmail.com>
|
||||
http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
|
||||
static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
|
||||
static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi)
|
||||
{
|
||||
int links = 0;
|
||||
struct route_node *rn;
|
||||
@ -624,7 +636,7 @@ static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
|
||||
}
|
||||
|
||||
/* Set router-LSA link information. */
|
||||
static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
|
||||
static int router_lsa_link_set(struct stream **s, struct ospf_area *area)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf_interface *oi;
|
||||
@ -667,28 +679,28 @@ static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
|
||||
}
|
||||
|
||||
/* Set router-LSA body. */
|
||||
static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area)
|
||||
static void ospf_router_lsa_body_set(struct stream **s, struct ospf_area *area)
|
||||
{
|
||||
unsigned long putp;
|
||||
uint16_t cnt;
|
||||
|
||||
/* Set flags. */
|
||||
stream_putc(s, router_lsa_flags(area));
|
||||
stream_putc(*s, router_lsa_flags(area));
|
||||
|
||||
/* Set Zero fields. */
|
||||
stream_putc(s, 0);
|
||||
stream_putc(*s, 0);
|
||||
|
||||
/* Keep pointer to # links. */
|
||||
putp = stream_get_endp(s);
|
||||
putp = stream_get_endp(*s);
|
||||
|
||||
/* Forward word */
|
||||
stream_putw(s, 0);
|
||||
stream_putw(*s, 0);
|
||||
|
||||
/* Set all link information. */
|
||||
cnt = router_lsa_link_set(s, area);
|
||||
|
||||
/* Set # of links here. */
|
||||
stream_putw_at(s, putp, cnt);
|
||||
stream_putw_at(*s, putp, cnt);
|
||||
}
|
||||
|
||||
static int ospf_stub_router_timer(struct thread *t)
|
||||
@ -773,7 +785,7 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
|
||||
OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
|
||||
|
||||
/* Set router-LSA body fields. */
|
||||
ospf_router_lsa_body_set(s, area);
|
||||
ospf_router_lsa_body_set(&s, area);
|
||||
|
||||
/* Set length. */
|
||||
length = stream_get_endp(s);
|
||||
@ -781,17 +793,13 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create OSPF LSA instance. */
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_err("%s: Unable to create new lsa", __func__);
|
||||
return NULL;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
new->area = area;
|
||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||
new->vrf_id = area->ospf->vrf_id;
|
||||
|
||||
/* Copy LSA data to store, discard stream. */
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
@ -997,17 +1005,13 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi)
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Create OSPF LSA instance. */
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_err("%s: ospf_lsa_new returned NULL", __func__);
|
||||
return NULL;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
new->area = oi->area;
|
||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||
new->vrf_id = oi->ospf->vrf_id;
|
||||
|
||||
/* Copy LSA to store. */
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
@ -1181,13 +1185,12 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Create OSPF LSA instance. */
|
||||
new = ospf_lsa_new();
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
new->area = area;
|
||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||
new->vrf_id = area->ospf->vrf_id;
|
||||
|
||||
/* Copy LSA to store. */
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
@ -1323,13 +1326,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Create OSPF LSA instance. */
|
||||
new = ospf_lsa_new();
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
new->area = area;
|
||||
SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
|
||||
new->vrf_id = area->ospf->vrf_id;
|
||||
|
||||
/* Copy LSA to store. */
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
@ -1629,14 +1631,13 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create OSPF LSA instance. */
|
||||
new = ospf_lsa_new();
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
new->area = NULL;
|
||||
SET_FLAG(new->flags,
|
||||
OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
|
||||
new->vrf_id = ospf->vrf_id;
|
||||
|
||||
/* Copy LSA data to store, discard stream. */
|
||||
new->data = ospf_lsa_data_new(length);
|
||||
memcpy(new->data, lsah, length);
|
||||
stream_free(s);
|
||||
|
||||
|
@ -235,6 +235,7 @@ extern int ospf_check_nbr_status(struct ospf *);
|
||||
|
||||
/* Prototype for LSA primitive. */
|
||||
extern struct ospf_lsa *ospf_lsa_new(void);
|
||||
extern struct ospf_lsa *ospf_lsa_new_and_data(size_t size);
|
||||
extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *);
|
||||
extern void ospf_lsa_free(struct ospf_lsa *);
|
||||
extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "ospfd/ospf_lsdb.h"
|
||||
#include "ospfd/ospf_neighbor.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_vty.h"
|
||||
#include "ospfd/ospf_bfd.h"
|
||||
|
@ -1742,7 +1742,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
|
||||
}
|
||||
|
||||
/* Create OSPF LSA instance. */
|
||||
lsa = ospf_lsa_new();
|
||||
lsa = ospf_lsa_new_and_data(length);
|
||||
|
||||
lsa->vrf_id = oi->ospf->vrf_id;
|
||||
/* We may wish to put some error checking if type NSSA comes in
|
||||
@ -1761,7 +1761,6 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
|
||||
break;
|
||||
}
|
||||
|
||||
lsa->data = ospf_lsa_data_new(length);
|
||||
memcpy(lsa->data, lsah, length);
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
|
@ -775,18 +775,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create an OSPF LSA instance. */
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
|
||||
zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
return new;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
|
||||
scope, fulfill otherwise */
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_ism.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
|
||||
/* OSPF2-MIB. */
|
||||
|
@ -1201,18 +1201,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
|
||||
lsah->length = htons(length);
|
||||
|
||||
/* Now, create an OSPF LSA instance. */
|
||||
if ((new = ospf_lsa_new()) == NULL) {
|
||||
zlog_warn("%s: ospf_lsa_new() ?", __func__);
|
||||
stream_free(s);
|
||||
return NULL;
|
||||
}
|
||||
if ((new->data = ospf_lsa_data_new(length)) == NULL) {
|
||||
zlog_warn("%s: ospf_lsa_data_new() ?", __func__);
|
||||
ospf_lsa_unlock(&new);
|
||||
new = NULL;
|
||||
stream_free(s);
|
||||
return new;
|
||||
}
|
||||
new = ospf_lsa_new_and_data(length);
|
||||
|
||||
new->vrf_id = ospf->vrf_id;
|
||||
if (area && area->ospf)
|
||||
|
@ -111,10 +111,11 @@ static int ospf_interface_add(int command, struct zclient *zclient,
|
||||
|
||||
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
|
||||
zlog_debug(
|
||||
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d",
|
||||
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u",
|
||||
ifp->name, ospf_vrf_id_to_name(ifp->vrf_id),
|
||||
ifp->vrf_id, ifp->ifindex,
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu,
|
||||
ifp->speed);
|
||||
|
||||
assert(ifp->info);
|
||||
|
||||
@ -128,6 +129,8 @@ static int ospf_interface_add(int command, struct zclient *zclient,
|
||||
if (!ospf)
|
||||
return 0;
|
||||
|
||||
ospf_if_recalculate_output_cost(ifp);
|
||||
|
||||
ospf_if_update(ospf, ifp);
|
||||
|
||||
hook_call(ospf_if_update, ifp);
|
||||
@ -448,14 +451,17 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
count++;
|
||||
|
||||
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
|
||||
char buf[2][PREFIX2STR_BUFFER];
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
struct interface *ifp;
|
||||
|
||||
ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id);
|
||||
|
||||
zlog_debug(
|
||||
"Zebra: Route add %s nexthop %s, ifindex=%d",
|
||||
"Zebra: Route add %s nexthop %s, ifindex=%d %s",
|
||||
prefix2str(p, buf[0], sizeof(buf[0])),
|
||||
inet_ntop(AF_INET, &path->nexthop,
|
||||
buf[1], sizeof(buf[1])),
|
||||
path->ifindex);
|
||||
path->ifindex, ifp ? ifp->name : " ");
|
||||
}
|
||||
}
|
||||
api.nexthop_num = count;
|
||||
|
@ -52,10 +52,10 @@
|
||||
#include "ospfd/ospf_spf.h"
|
||||
#include "ospfd/ospf_packet.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_ase.h"
|
||||
|
||||
|
||||
|
@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
struct pim_assert_metric *am;
|
||||
struct in_addr ifaddr;
|
||||
char pref_str[5];
|
||||
char metr_str[7];
|
||||
char pref_str[16];
|
||||
char metr_str[16];
|
||||
|
||||
ifaddr = pim_ifp->primary_address;
|
||||
|
||||
|
@ -1495,14 +1495,6 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pim_if_is_loopback(struct interface *ifp)
|
||||
{
|
||||
if (if_is_loopback(ifp) || if_is_vrf(ifp))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pim_if_is_vrf_device(struct interface *ifp)
|
||||
{
|
||||
if (if_is_vrf(ifp))
|
||||
|
@ -207,8 +207,6 @@ void pim_if_create_pimreg(struct pim_instance *pim);
|
||||
int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
|
||||
int pim_update_source_set(struct interface *ifp, struct in_addr source);
|
||||
|
||||
bool pim_if_is_loopback(struct interface *ifp);
|
||||
|
||||
bool pim_if_is_vrf_device(struct interface *ifp);
|
||||
|
||||
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
|
||||
|
@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
ifchannel list is empty before deleting upstream_del
|
||||
ref count will take care of it.
|
||||
*/
|
||||
pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
|
||||
if (ch->upstream->ref_count > 0)
|
||||
pim_upstream_del(pim_ifp->pim, ch->upstream,
|
||||
__PRETTY_FUNCTION__);
|
||||
|
||||
else
|
||||
zlog_warn("%s: Avoiding deletion of upstream with ref_count %d "
|
||||
"from ifchannel(%s): %s", __PRETTY_FUNCTION__,
|
||||
ch->upstream->ref_count, ch->interface->name,
|
||||
ch->sg_str);
|
||||
|
||||
ch->upstream = NULL;
|
||||
|
||||
THREAD_OFF(ch->t_ifjoin_expiry_timer);
|
||||
|
@ -37,19 +37,20 @@
|
||||
|
||||
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
||||
{
|
||||
char *out;
|
||||
struct prefix_sg sg;
|
||||
int i;
|
||||
|
||||
sg.src = c_oil->oil.mfcc_origin;
|
||||
sg.grp = c_oil->oil.mfcc_mcastgrp;
|
||||
sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
|
||||
c_oil->oil.mfcc_parent);
|
||||
snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
|
||||
c_oil->oil.mfcc_parent);
|
||||
|
||||
out = buf + strlen(buf);
|
||||
for (i = 0; i < MAXVIFS; i++) {
|
||||
if (c_oil->oil.mfcc_ttls[i] != 0) {
|
||||
char buf1[10];
|
||||
sprintf(buf1, "%d ", i);
|
||||
strcat(buf, buf1);
|
||||
snprintf(out, buf + size - out, "%d ", i);
|
||||
out += strlen(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,7 +655,7 @@ static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
|
||||
if (pim_if_is_loopback(ifp))
|
||||
if (if_is_loopback_or_vrf(ifp))
|
||||
return 0;
|
||||
|
||||
if (hello_send(ifp, holdtime)) {
|
||||
@ -757,7 +757,7 @@ void pim_hello_restart_triggered(struct interface *ifp)
|
||||
/*
|
||||
* No need to ever start loopback or vrf device hello's
|
||||
*/
|
||||
if (pim_if_is_loopback(ifp))
|
||||
if (if_is_loopback_or_vrf(ifp))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
|
||||
up->ref_count, up->flags,
|
||||
up->channel_oil->oil_ref_count);
|
||||
|
||||
assert(up->ref_count > 0);
|
||||
|
||||
--up->ref_count;
|
||||
|
||||
if (up->ref_count >= 1)
|
||||
|
@ -31,7 +31,7 @@ Commands defined by this snap
|
||||
- `frr.readme`:
|
||||
Returns this document `cat README_usage.md`
|
||||
- `frr.set`:
|
||||
Allows to enable `FPM` module. See FPM section below
|
||||
Allows to enable `FPM` and/or disable RPKIi module. See Module section below
|
||||
|
||||
and for debugging defined at this time (May get removed later - do not
|
||||
depend on them). These are mainly intended to debug the Snap
|
||||
@ -100,13 +100,13 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in
|
||||
These settings require either a reboot or a manual configuration with
|
||||
`sysctl` as well.
|
||||
|
||||
FPM Module
|
||||
Modules
|
||||
----------
|
||||
The `frr.set` allows to turn FPM module on or off.
|
||||
The `frr.set` allows to turn FPM module ond the RPKI module on or off.
|
||||
|
||||
frr.set fpm {disable|protobuf|netlink}
|
||||
|
||||
Disables FPM or enables FPM with selected mode
|
||||
Disables FPM or enables FPM with selected mode (default: disabled)
|
||||
|
||||
By default, the FPM module is disabled, but installed with netlink and
|
||||
protobuf support. To enable the FPM module, use the `frr.set fpm protobuf`
|
||||
@ -114,6 +114,17 @@ or `frr.set fpm netlink` command. The command will only enable the mode
|
||||
for the next restart of zebra. Please reboot or restart zebra after
|
||||
changing the mode to become effective.
|
||||
|
||||
frr.set rpki {enable|disable}
|
||||
|
||||
Disables or enables BGP RPKI (default: enabled)
|
||||
|
||||
By default, the RPKI module is enabled. To disable the RPKI module
|
||||
use the `frr.set rpki disable` command. The command will only enable
|
||||
the module after the next restart of the bgp daemon. Please reboot or
|
||||
restart bgpd after changing the mode to become effective.
|
||||
(Normally, there is no need to disable the module as it has no effect
|
||||
if there are no RPKI configurations in BGP)
|
||||
|
||||
FAQ
|
||||
---
|
||||
- frr.vtysh displays `--MORE--` on long output. How to suppress this?
|
||||
|
@ -5,9 +5,16 @@ set -e -x
|
||||
if ! [ -e $SNAP_DATA/bgpd.conf ]; then
|
||||
cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
|
||||
fi
|
||||
# If no RPKI option is specified, then we create a default
|
||||
# with RPKI enabled
|
||||
if ! [ -e $SNAP_DATA/rpki.conf ]; then
|
||||
echo "-M rpki" > $SNAP_DATA/rpki.conf
|
||||
fi
|
||||
EXTRA_OPTIONS="`cat $SNAP_DATA/rpki.conf`"
|
||||
exec $SNAP/sbin/bgpd \
|
||||
-f $SNAP_DATA/bgpd.conf \
|
||||
--pid_file $SNAP_DATA/bgpd.pid \
|
||||
--socket $SNAP_DATA/zsock \
|
||||
--vty_socket $SNAP_DATA
|
||||
--vty_socket $SNAP_DATA \
|
||||
--moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS
|
||||
|
||||
|
@ -28,11 +28,34 @@ case $1 in
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
rpki)
|
||||
case $2 in
|
||||
disable)
|
||||
echo "" > $SNAP_DATA/rpki.conf
|
||||
echo "RPKI module disabled. Please restart FRR"
|
||||
;;
|
||||
enable)
|
||||
echo "-M rpki" > $SNAP_DATA/rpki.conf
|
||||
echo "RPKI module enabled. Please restart FRR"
|
||||
;;
|
||||
*)
|
||||
echo "Usage:"
|
||||
echo " ${SNAP_NAME}.set rpki {disable|enable}"
|
||||
echo ""
|
||||
echo " Disables BGP RPKI module or enables it (default: enabled)"
|
||||
echo " Mode will be saved for next restart of bgpd, but bgpd"
|
||||
echo " is not automatically restarted"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage:"
|
||||
echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
|
||||
echo " ${SNAP_NAME}.set rpki {disable|enable}"
|
||||
echo ""
|
||||
echo " Disables FPM or enables FPM with selected mode"
|
||||
echo " fpm: Disables FPM or enables FPM with selected mode"
|
||||
echo " rpki: Disables BGP RPKI or enables it (default: enabled)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
@ -136,7 +136,7 @@ apps:
|
||||
- network-bind
|
||||
- network-control
|
||||
bgpd-debug:
|
||||
command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
|
||||
command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA --moduledir $SNAP/lib/frr/modules `cat $SNAP_DATA/rpki.conf 2> /dev/null`
|
||||
plugs:
|
||||
- network
|
||||
- network-bind
|
||||
@ -221,8 +221,27 @@ apps:
|
||||
- network-control
|
||||
|
||||
parts:
|
||||
rtrlib:
|
||||
build-packages:
|
||||
- cmake
|
||||
- make
|
||||
- gcc
|
||||
- libssh-dev
|
||||
stage-packages:
|
||||
- libssh-4
|
||||
prime:
|
||||
- lib/x86_64-linux-gnu/librtr.so*
|
||||
- usr/lib/x86_64-linux-gnu/libssh.so*
|
||||
source: https://github.com/rtrlib/rtrlib.git
|
||||
source-type: git
|
||||
source-tag: v0.5.0
|
||||
plugin: cmake
|
||||
configflags:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
frr:
|
||||
build-packages:
|
||||
after: [rtrlib]
|
||||
build-packages:
|
||||
- gcc
|
||||
- autoconf
|
||||
- automake
|
||||
- libtool
|
||||
@ -247,6 +266,7 @@ parts:
|
||||
- flex
|
||||
- python3-dev
|
||||
- protobuf-c-compiler
|
||||
- python3-sphinx
|
||||
stage-packages:
|
||||
- coreutils
|
||||
- iproute2
|
||||
@ -276,6 +296,7 @@ parts:
|
||||
- --enable-ldpd
|
||||
- --enable-fpm
|
||||
- --enable-protobuf
|
||||
- --enable-rpki
|
||||
- --enable-configfile-mask=0640
|
||||
- --enable-logfile-mask=0640
|
||||
- --localstatedir=/var/run
|
||||
|
@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole,
|
||||
"Table to configure\n"
|
||||
"The table number to configure\n")
|
||||
{
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf,
|
||||
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
||||
struct static_vrf *svrf = vrf->info;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf,
|
||||
struct static_vrf *svrf = vrf->info;
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -984,7 +984,7 @@ DEFPY(ip_route,
|
||||
struct static_vrf *nh_svrf;
|
||||
const char *flag = NULL;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf,
|
||||
struct static_vrf *nh_svrf;
|
||||
const char *flag = NULL;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole,
|
||||
"Table to configure\n"
|
||||
"The table number to configure\n")
|
||||
{
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf,
|
||||
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
||||
struct static_vrf *svrf = vrf->info;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface,
|
||||
struct static_vrf *svrf;
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf,
|
||||
struct static_vrf *svrf = vrf->info;
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1309,7 +1309,7 @@ DEFPY(ipv6_route,
|
||||
struct static_vrf *svrf;
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf,
|
||||
struct static_vrf *svrf = vrf->info;
|
||||
struct static_vrf *nh_svrf;
|
||||
|
||||
if (table_str && !vrf_is_backend_netns()) {
|
||||
if (table_str && !vrf_is_mapped_on_netns(vrf)) {
|
||||
vty_out(vty,
|
||||
"%% table param only available when running on netns-based vrfs\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "log.h"
|
||||
#include "nexthop.h"
|
||||
#include "nexthop_group.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include "static_vrf.h"
|
||||
#include "static_routes.h"
|
||||
@ -43,6 +44,7 @@
|
||||
|
||||
/* Zebra structure to hold current status. */
|
||||
struct zclient *zclient;
|
||||
static struct hash *static_nht_hash;
|
||||
|
||||
static struct interface *zebra_interface_if_lookup(struct stream *s)
|
||||
{
|
||||
@ -176,10 +178,16 @@ static void zebra_connected(struct zclient *zclient)
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
struct static_nht_data {
|
||||
struct prefix *nh;
|
||||
uint32_t refcount;
|
||||
uint8_t nh_num;
|
||||
};
|
||||
|
||||
static int static_zebra_nexthop_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct static_nht_data *nhtd, lookup;
|
||||
struct zapi_route nhr;
|
||||
afi_t afi = AFI_IP;
|
||||
|
||||
@ -191,6 +199,14 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
|
||||
if (nhr.prefix.family == AF_INET6)
|
||||
afi = AFI_IP6;
|
||||
|
||||
memset(&lookup, 0, sizeof(lookup));
|
||||
lookup.nh = &nhr.prefix;
|
||||
|
||||
nhtd = hash_lookup(static_nht_hash, &lookup);
|
||||
if (nhtd)
|
||||
nhtd->nh_num = nhr.nexthop_num;
|
||||
|
||||
|
||||
static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
|
||||
return 1;
|
||||
}
|
||||
@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
|
||||
mpls_enabled = cap->mpls_enabled;
|
||||
}
|
||||
|
||||
static unsigned int static_nht_hash_key(void *data)
|
||||
{
|
||||
struct static_nht_data *nhtd = data;
|
||||
|
||||
return prefix_hash_key(nhtd->nh);
|
||||
}
|
||||
|
||||
static int static_nht_hash_cmp(const void *d1, const void *d2)
|
||||
{
|
||||
const struct static_nht_data *nhtd1 = d1;
|
||||
const struct static_nht_data *nhtd2 = d2;
|
||||
|
||||
return prefix_same(nhtd1->nh, nhtd2->nh);
|
||||
}
|
||||
|
||||
static void *static_nht_hash_alloc(void *data)
|
||||
{
|
||||
struct static_nht_data *copy = data;
|
||||
struct static_nht_data *new;
|
||||
|
||||
new = XMALLOC(MTYPE_TMP, sizeof(*new));
|
||||
|
||||
new->nh = prefix_new();
|
||||
prefix_copy(new->nh, copy->nh);
|
||||
new->refcount = 0;
|
||||
new->nh_num = 0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static void static_nht_hash_free(void *data)
|
||||
{
|
||||
struct static_nht_data *nhtd = data;
|
||||
|
||||
prefix_free(nhtd->nh);
|
||||
XFREE(MTYPE_TMP, nhtd);
|
||||
}
|
||||
|
||||
void static_zebra_nht_register(struct static_route *si, bool reg)
|
||||
{
|
||||
struct static_nht_data *nhtd, lookup;
|
||||
uint32_t cmd;
|
||||
struct prefix p;
|
||||
afi_t afi = AFI_IP;
|
||||
|
||||
cmd = (reg) ?
|
||||
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
|
||||
@ -224,20 +280,48 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_BITLEN;
|
||||
p.u.prefix4 = si->addr.ipv4;
|
||||
afi = AFI_IP;
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
case STATIC_IPV6_GATEWAY_IFNAME:
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_BITLEN;
|
||||
p.u.prefix6 = si->addr.ipv6;
|
||||
afi = AFI_IP6;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&lookup, 0, sizeof(lookup));
|
||||
lookup.nh = &p;
|
||||
|
||||
si->nh_registered = reg;
|
||||
|
||||
if (reg) {
|
||||
nhtd = hash_get(static_nht_hash, &lookup,
|
||||
static_nht_hash_alloc);
|
||||
nhtd->refcount++;
|
||||
|
||||
if (nhtd->refcount > 1) {
|
||||
static_nht_update(nhtd->nh, nhtd->nh_num,
|
||||
afi, si->nh_vrf_id);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
nhtd = hash_lookup(static_nht_hash, &lookup);
|
||||
if (!nhtd)
|
||||
return;
|
||||
|
||||
nhtd->refcount--;
|
||||
if (nhtd->refcount >= 1)
|
||||
return;
|
||||
|
||||
hash_release(static_nht_hash, nhtd);
|
||||
static_nht_hash_free(nhtd);
|
||||
}
|
||||
|
||||
if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
|
||||
zlog_warn("%s: Failure to send nexthop to zebra",
|
||||
__PRETTY_FUNCTION__);
|
||||
|
||||
si->nh_registered = reg;
|
||||
}
|
||||
|
||||
extern void static_zebra_route_add(struct route_node *rn,
|
||||
@ -273,9 +357,10 @@ extern void static_zebra_route_add(struct route_node *rn,
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
|
||||
api.tag = si_changed->tag;
|
||||
}
|
||||
api.tableid = si_changed->table_id;
|
||||
|
||||
zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
|
||||
if (si_changed->table_id != 0) {
|
||||
SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
|
||||
api.tableid = si_changed->table_id;
|
||||
}
|
||||
for (/*loaded above*/; si; si = si->next) {
|
||||
api_nh = &api.nexthops[nh_num];
|
||||
if (si->nh_vrf_id == VRF_UNKNOWN)
|
||||
@ -372,4 +457,8 @@ void static_zebra_init(void)
|
||||
zclient->interface_address_delete = interface_address_delete;
|
||||
zclient->route_notify_owner = route_notify_owner;
|
||||
zclient->nexthop_update = static_zebra_nexthop_update;
|
||||
|
||||
static_nht_hash = hash_create(static_nht_hash_key,
|
||||
static_nht_hash_cmp,
|
||||
"Static Nexthop Tracking hash");
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
|
||||
switch (type) {
|
||||
case CAPABILITY:
|
||||
len += 2; /* to cover the OPT-Param header */
|
||||
__attribute__ ((fallthrough));
|
||||
_FALLTHROUGH
|
||||
case OPT_PARAM:
|
||||
printf("len: %u\n", len);
|
||||
/* peek_for_as4 wants getp at capibility*/
|
||||
|
@ -57,7 +57,7 @@ int main(void)
|
||||
|
||||
print_stream(s);
|
||||
|
||||
stream_resize(s, stream_get_endp(s));
|
||||
stream_resize_inplace(&s, stream_get_endp(s));
|
||||
|
||||
print_stream(s);
|
||||
|
||||
|
@ -1435,24 +1435,6 @@ DEFUNSH(VTYSH_BGPD,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD,
|
||||
rpki_exit,
|
||||
rpki_exit_cmd,
|
||||
"exit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
vty->node = CONFIG_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD,
|
||||
rpki_quit,
|
||||
rpki_quit_cmd,
|
||||
"quit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
return rpki_exit(self, vty, argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
|
||||
@ -1790,6 +1772,7 @@ static int vtysh_exit(struct vty *vty)
|
||||
case VTY_NODE:
|
||||
case KEYCHAIN_NODE:
|
||||
case BFD_NODE:
|
||||
case RPKI_NODE:
|
||||
vtysh_execute("end");
|
||||
vtysh_execute("configure terminal");
|
||||
vty->node = CONFIG_NODE;
|
||||
@ -1883,8 +1866,24 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
|
||||
|| vty->node == BGP_VNC_L2_GROUP_NODE)
|
||||
vty->node = BGP_NODE;
|
||||
return CMD_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
#if defined(HAVE_RPKI)
|
||||
DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
vtysh_exit(vty);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
return rpki_exit(self, vty, argc, argv);
|
||||
}
|
||||
#endif /* HAVE_RPKI */
|
||||
|
||||
DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
|
||||
"Exit from VRF configuration mode\n")
|
||||
{
|
||||
|
@ -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/rib.h"
|
||||
#include "zebra/rt.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,
|
||||
const void *data, unsigned int alen)
|
||||
{
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
|
||||
struct rtattr *rta, int len);
|
||||
extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
|
||||
struct rtattr *rta);
|
||||
extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
|
||||
const void *data, unsigned int alen);
|
||||
extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
|
||||
|
@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
|
||||
return write;
|
||||
}
|
||||
|
||||
void zebra_import_table_rm_update()
|
||||
void zebra_import_table_rm_update(const char *rmap)
|
||||
{
|
||||
afi_t afi;
|
||||
int i;
|
||||
@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
|
||||
continue;
|
||||
|
||||
rmap_name = zebra_get_import_table_route_map(afi, i);
|
||||
if (!rmap_name)
|
||||
return;
|
||||
|
||||
if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
|
||||
continue;
|
||||
table = zebra_vrf_other_route_table(afi, i,
|
||||
VRF_DEFAULT);
|
||||
for (rn = route_top(table); rn; rn = route_next(rn)) {
|
||||
|
@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);
|
||||
|
||||
extern int zebra_import_table_config(struct vty *);
|
||||
|
||||
extern void zebra_import_table_rm_update(void);
|
||||
|
||||
extern void zebra_import_table_rm_update(const char *rmap);
|
||||
#endif /* _ZEBRA_REDISTRIBUTE_H */
|
||||
|
@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
|
||||
vrf_id_t vrf_id);
|
||||
|
||||
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
|
||||
extern void rib_update_table(struct route_table *table,
|
||||
rib_update_event_t event);
|
||||
extern void rib_sweep_route(void);
|
||||
extern void rib_sweep_table(struct route_table *table);
|
||||
extern void rib_close_table(struct route_table *table);
|
||||
|
@ -246,6 +246,33 @@ static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
|
||||
return VRF_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @parse_encap_mpls() - Parses encapsulated mpls attributes
|
||||
* @tb: Pointer to rtattr to look for nested items in.
|
||||
* @labels: Pointer to store labels in.
|
||||
*
|
||||
* Return: Number of mpls labels found.
|
||||
*/
|
||||
static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
|
||||
{
|
||||
struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
|
||||
mpls_lse_t *lses = NULL;
|
||||
int num_labels = 0;
|
||||
uint32_t ttl = 0;
|
||||
uint32_t bos = 0;
|
||||
uint32_t exp = 0;
|
||||
mpls_label_t label = 0;
|
||||
|
||||
netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
|
||||
lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
|
||||
while (!bos && num_labels < MPLS_MAX_LABELS) {
|
||||
mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
|
||||
labels[num_labels++] = label;
|
||||
}
|
||||
|
||||
return num_labels;
|
||||
}
|
||||
|
||||
/* Looking up routing table by netlink interface. */
|
||||
static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
int startup)
|
||||
@ -274,6 +301,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
void *src = NULL; /* IPv6 srcdest source prefix */
|
||||
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
||||
|
||||
/* MPLS labels */
|
||||
mpls_label_t labels[MPLS_MAX_LABELS] = {0};
|
||||
int num_labels = 0;
|
||||
|
||||
rtm = NLMSG_DATA(h);
|
||||
|
||||
if (startup && h->nlmsg_type != RTM_NEWROUTE)
|
||||
@ -508,6 +539,17 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
}
|
||||
nh.vrf_id = nh_vrf_id;
|
||||
|
||||
if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
|
||||
&& *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
|
||||
== LWTUNNEL_ENCAP_MPLS) {
|
||||
num_labels =
|
||||
parse_encap_mpls(tb[RTA_ENCAP], labels);
|
||||
}
|
||||
|
||||
if (num_labels)
|
||||
nexthop_add_labels(&nh, ZEBRA_LSP_STATIC,
|
||||
num_labels, labels);
|
||||
|
||||
rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
|
||||
&src_p, &nh, table, metric, mtu, distance, tag);
|
||||
} else {
|
||||
@ -532,6 +574,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
re->tag = tag;
|
||||
|
||||
for (;;) {
|
||||
struct nexthop *nh = NULL;
|
||||
vrf_id_t nh_vrf_id;
|
||||
if (len < (int)sizeof(*rtnh)
|
||||
|| rtnh->rtnh_len > len)
|
||||
@ -569,35 +612,46 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
if (tb[RTA_GATEWAY])
|
||||
gate = RTA_DATA(
|
||||
tb[RTA_GATEWAY]);
|
||||
if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
|
||||
&& *(uint16_t *)RTA_DATA(
|
||||
tb[RTA_ENCAP_TYPE])
|
||||
== LWTUNNEL_ENCAP_MPLS) {
|
||||
num_labels = parse_encap_mpls(
|
||||
tb[RTA_ENCAP], labels);
|
||||
}
|
||||
}
|
||||
|
||||
if (gate) {
|
||||
if (rtm->rtm_family == AF_INET) {
|
||||
if (index)
|
||||
route_entry_nexthop_ipv4_ifindex_add(
|
||||
nh = route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, gate,
|
||||
prefsrc, index,
|
||||
nh_vrf_id);
|
||||
else
|
||||
route_entry_nexthop_ipv4_add(
|
||||
nh = route_entry_nexthop_ipv4_add(
|
||||
re, gate,
|
||||
prefsrc,
|
||||
nh_vrf_id);
|
||||
} else if (rtm->rtm_family
|
||||
== AF_INET6) {
|
||||
if (index)
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
nh = route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, gate, index,
|
||||
nh_vrf_id);
|
||||
else
|
||||
route_entry_nexthop_ipv6_add(
|
||||
nh = route_entry_nexthop_ipv6_add(
|
||||
re, gate,
|
||||
nh_vrf_id);
|
||||
}
|
||||
} else
|
||||
route_entry_nexthop_ifindex_add(
|
||||
nh = route_entry_nexthop_ifindex_add(
|
||||
re, index, nh_vrf_id);
|
||||
|
||||
if (nh && num_labels)
|
||||
nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
|
||||
num_labels, labels);
|
||||
|
||||
if (rtnh->rtnh_len == 0)
|
||||
break;
|
||||
|
||||
|
@ -141,13 +141,3 @@ if DEV_BUILD
|
||||
zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
zebra/GNOME-SMI \
|
||||
zebra/GNOME-PRODUCT-ZEBRA-MIB \
|
||||
# end
|
||||
|
||||
# -- unmaintained --
|
||||
# noinst_PROGRAMS += zebra/client
|
||||
# zebra_client_SOURCES = zebra/client_main.c
|
||||
# zebra_client_LDADD = lib/libfrr.la
|
||||
|
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;
|
||||
uint8_t flags = 0;
|
||||
uint16_t type = cmd2type[hdr->command];
|
||||
bool exist;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT)
|
||||
zlog_debug(
|
||||
@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
p.family);
|
||||
return;
|
||||
}
|
||||
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
|
||||
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
|
||||
if (!rnh)
|
||||
return;
|
||||
|
||||
if (type == RNH_NEXTHOP_TYPE) {
|
||||
if (flags
|
||||
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
||||
@ -1084,7 +1088,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
|
||||
zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
|
||||
/* Anything not AF_INET/INET6 has been filtered out above */
|
||||
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
|
||||
if (!exist)
|
||||
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type,
|
||||
&p);
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
@ -1584,202 +1590,6 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
/* This function support multiple nexthop. */
|
||||
/*
|
||||
* Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
|
||||
* add kernel route.
|
||||
*/
|
||||
static void zread_ipv4_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
int i;
|
||||
struct route_entry *re;
|
||||
struct prefix p;
|
||||
uint8_t message;
|
||||
struct in_addr nhop_addr;
|
||||
uint8_t nexthop_num;
|
||||
uint8_t nexthop_type;
|
||||
struct stream *s;
|
||||
ifindex_t ifindex;
|
||||
safi_t safi;
|
||||
int ret;
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
s = msg;
|
||||
|
||||
/* Allocate new re. */
|
||||
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
||||
|
||||
/* Type, flags, message. */
|
||||
STREAM_GETC(s, re->type);
|
||||
if (re->type > ZEBRA_ROUTE_MAX) {
|
||||
zlog_warn("%s: Specified route type %d is not a legal value\n",
|
||||
__PRETTY_FUNCTION__, re->type);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GETW(s, re->instance);
|
||||
STREAM_GETL(s, re->flags);
|
||||
STREAM_GETC(s, message);
|
||||
STREAM_GETW(s, safi);
|
||||
re->uptime = time(NULL);
|
||||
|
||||
/* IPv4 prefix. */
|
||||
memset(&p, 0, sizeof(struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
if (p.prefixlen > IPV4_MAX_BITLEN) {
|
||||
zlog_warn(
|
||||
"%s: Specified prefix length %d is greater than what v4 can be",
|
||||
__PRETTY_FUNCTION__, p.prefixlen);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/* Nexthop parse. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
STREAM_GETC(s, nexthop_num);
|
||||
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
||||
nexthop_num);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
label_type = lsp_type_from_re_type(client->proto);
|
||||
|
||||
for (i = 0; i < nexthop_num; i++) {
|
||||
STREAM_GETC(s, nexthop_type);
|
||||
|
||||
switch (nexthop_type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ifindex_add(re, ifindex,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
STREAM_GET(&nhop_addr.s_addr, s,
|
||||
IPV4_MAX_BYTELEN);
|
||||
nexthop = route_entry_nexthop_ipv4_add(
|
||||
re, &nhop_addr, NULL, re->vrf_id);
|
||||
/*
|
||||
* For labeled-unicast, each nexthop is followed
|
||||
* by the label.
|
||||
*/
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
|
||||
STREAM_GETL(s, label);
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &label);
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
STREAM_GET(&nhop_addr.s_addr, s,
|
||||
IPV4_MAX_BYTELEN);
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &nhop_addr, NULL, ifindex,
|
||||
re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
zlog_warn(
|
||||
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops",
|
||||
__PRETTY_FUNCTION__);
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
default:
|
||||
zlog_warn(
|
||||
"%s: Specified nexthop type: %d does not exist",
|
||||
__PRETTY_FUNCTION__, nexthop_type);
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Distance. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
||||
STREAM_GETC(s, re->distance);
|
||||
|
||||
/* Metric. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
||||
STREAM_GETL(s, re->metric);
|
||||
|
||||
/* Tag */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
||||
STREAM_GETL(s, re->tag);
|
||||
else
|
||||
re->tag = 0;
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
||||
STREAM_GETL(s, re->mtu);
|
||||
else
|
||||
re->mtu = 0;
|
||||
|
||||
/* Table */
|
||||
re->table = zvrf->table_id;
|
||||
|
||||
ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re);
|
||||
|
||||
/* Stats */
|
||||
if (ret > 0)
|
||||
client->v4_route_add_cnt++;
|
||||
else if (ret < 0)
|
||||
client->v4_route_upd8_cnt++;
|
||||
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
}
|
||||
|
||||
/* Zebra server IPv4 prefix delete function. */
|
||||
static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv4 api;
|
||||
struct prefix p;
|
||||
uint32_t table_id;
|
||||
|
||||
s = msg;
|
||||
|
||||
/* Type, flags, message. */
|
||||
STREAM_GETC(s, api.type);
|
||||
STREAM_GETW(s, api.instance);
|
||||
STREAM_GETL(s, api.flags);
|
||||
STREAM_GETC(s, api.message);
|
||||
STREAM_GETW(s, api.safi);
|
||||
|
||||
/* IPv4 prefix. */
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
p.family = AF_INET;
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
if (p.prefixlen > IPV4_MAX_BITLEN) {
|
||||
zlog_warn("%s: Passed in prefixlen %d is impossible",
|
||||
__PRETTY_FUNCTION__, p.prefixlen);
|
||||
return;
|
||||
}
|
||||
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
||||
|
||||
table_id = zvrf->table_id;
|
||||
|
||||
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||
api.flags, &p, NULL, NULL, table_id, 0, 0, false);
|
||||
client->v4_route_del_cnt++;
|
||||
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
/* MRIB Nexthop lookup for IPv4. */
|
||||
static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
@ -1794,417 +1604,6 @@ stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Zebra server IPv6 prefix add function. */
|
||||
static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
unsigned int i;
|
||||
struct stream *s;
|
||||
struct in6_addr nhop_addr;
|
||||
struct route_entry *re;
|
||||
uint8_t message;
|
||||
uint8_t nexthop_num;
|
||||
uint8_t nexthop_type;
|
||||
struct prefix p;
|
||||
safi_t safi;
|
||||
static struct in6_addr nexthops[MULTIPATH_NUM];
|
||||
static unsigned int ifindices[MULTIPATH_NUM];
|
||||
int ret;
|
||||
static mpls_label_t labels[MULTIPATH_NUM];
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
s = msg;
|
||||
|
||||
memset(&nhop_addr, 0, sizeof(struct in6_addr));
|
||||
|
||||
/* Allocate new re. */
|
||||
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
||||
|
||||
/* Type, flags, message. */
|
||||
STREAM_GETC(s, re->type);
|
||||
if (re->type > ZEBRA_ROUTE_MAX) {
|
||||
zlog_warn("%s: Specified route type: %d is not a legal value\n",
|
||||
__PRETTY_FUNCTION__, re->type);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GETW(s, re->instance);
|
||||
STREAM_GETL(s, re->flags);
|
||||
STREAM_GETC(s, message);
|
||||
STREAM_GETW(s, safi);
|
||||
re->uptime = time(NULL);
|
||||
|
||||
/* IPv4 prefix. */
|
||||
memset(&p, 0, sizeof(struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
if (p.prefixlen > IPV4_MAX_BITLEN) {
|
||||
zlog_warn(
|
||||
"%s: Prefix Length %d is greater than what a v4 address can use",
|
||||
__PRETTY_FUNCTION__, p.prefixlen);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/*
|
||||
* We need to give nh-addr, nh-ifindex with the same next-hop object
|
||||
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
||||
* these. Clients should send the same number of paired set of
|
||||
* next-hop-addr/next-hop-ifindices.
|
||||
*/
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
unsigned int nh_count = 0;
|
||||
unsigned int if_count = 0;
|
||||
unsigned int max_nh_if = 0;
|
||||
|
||||
STREAM_GETC(s, nexthop_num);
|
||||
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
||||
nexthop_num);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
label_type = lsp_type_from_re_type(client->proto);
|
||||
|
||||
for (i = 0; i < nexthop_num; i++) {
|
||||
STREAM_GETC(s, nexthop_type);
|
||||
|
||||
switch (nexthop_type) {
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
STREAM_GET(&nhop_addr, s, 16);
|
||||
if (nh_count < MULTIPATH_NUM) {
|
||||
/*
|
||||
* For labeled-unicast, each nexthop is
|
||||
* followed by the label.
|
||||
*/
|
||||
if (CHECK_FLAG(message,
|
||||
ZAPI_MESSAGE_LABEL)) {
|
||||
STREAM_GETL(s, label);
|
||||
labels[nh_count] = label;
|
||||
}
|
||||
nexthops[nh_count] = nhop_addr;
|
||||
nh_count++;
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
if (if_count < multipath_num)
|
||||
STREAM_GETL(s, ifindices[if_count++]);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
default:
|
||||
zlog_warn(
|
||||
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
|
||||
__PRETTY_FUNCTION__);
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
|
||||
for (i = 0; i < max_nh_if; i++) {
|
||||
if ((i < nh_count)
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
nexthop =
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nexthops[i],
|
||||
ifindices[i],
|
||||
re->vrf_id);
|
||||
else
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &nexthops[i], re->vrf_id);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &labels[i]);
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
route_entry_nexthop_ifindex_add(
|
||||
re, ifindices[i], re->vrf_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Distance. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
||||
STREAM_GETC(s, re->distance);
|
||||
|
||||
/* Metric. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
||||
STREAM_GETL(s, re->metric);
|
||||
|
||||
/* Tag */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
||||
STREAM_GETL(s, re->tag);
|
||||
else
|
||||
re->tag = 0;
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
||||
STREAM_GETL(s, re->mtu);
|
||||
else
|
||||
re->mtu = 0;
|
||||
|
||||
/* Table */
|
||||
re->table = zvrf->table_id;
|
||||
|
||||
ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re);
|
||||
/* Stats */
|
||||
if (ret > 0)
|
||||
client->v4_route_add_cnt++;
|
||||
else if (ret < 0)
|
||||
client->v4_route_upd8_cnt++;
|
||||
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
}
|
||||
|
||||
static void zread_ipv6_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
unsigned int i;
|
||||
struct stream *s;
|
||||
struct in6_addr nhop_addr;
|
||||
ifindex_t ifindex;
|
||||
struct route_entry *re;
|
||||
uint8_t message;
|
||||
uint8_t nexthop_num;
|
||||
uint8_t nexthop_type;
|
||||
struct prefix p;
|
||||
struct prefix_ipv6 src_p, *src_pp;
|
||||
safi_t safi;
|
||||
static struct in6_addr nexthops[MULTIPATH_NUM];
|
||||
static unsigned int ifindices[MULTIPATH_NUM];
|
||||
int ret;
|
||||
static mpls_label_t labels[MULTIPATH_NUM];
|
||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
s = msg;
|
||||
|
||||
memset(&nhop_addr, 0, sizeof(struct in6_addr));
|
||||
|
||||
/* Allocate new re. */
|
||||
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
|
||||
|
||||
/* Type, flags, message. */
|
||||
STREAM_GETC(s, re->type);
|
||||
if (re->type > ZEBRA_ROUTE_MAX) {
|
||||
zlog_warn("%s: Specified route type: %d is not a legal value\n",
|
||||
__PRETTY_FUNCTION__, re->type);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GETW(s, re->instance);
|
||||
STREAM_GETL(s, re->flags);
|
||||
STREAM_GETC(s, message);
|
||||
STREAM_GETW(s, safi);
|
||||
re->uptime = time(NULL);
|
||||
|
||||
/* IPv6 prefix. */
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.family = AF_INET6;
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
if (p.prefixlen > IPV6_MAX_BITLEN) {
|
||||
zlog_warn(
|
||||
"%s: Specified prefix length %d is to large for v6 prefix",
|
||||
__PRETTY_FUNCTION__, p.prefixlen);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) {
|
||||
memset(&src_p, 0, sizeof(src_p));
|
||||
src_p.family = AF_INET6;
|
||||
STREAM_GETC(s, src_p.prefixlen);
|
||||
if (src_p.prefixlen > IPV6_MAX_BITLEN) {
|
||||
zlog_warn(
|
||||
"%s: Specified src prefix length %d is to large for v6 prefix",
|
||||
__PRETTY_FUNCTION__, src_p.prefixlen);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
|
||||
src_pp = &src_p;
|
||||
} else
|
||||
src_pp = NULL;
|
||||
|
||||
/* VRF ID */
|
||||
re->vrf_id = zvrf_id(zvrf);
|
||||
|
||||
/*
|
||||
* We need to give nh-addr, nh-ifindex with the same next-hop object
|
||||
* to the re to ensure that IPv6 multipathing works; need to coalesce
|
||||
* these. Clients should send the same number of paired set of
|
||||
* next-hop-addr/next-hop-ifindices.
|
||||
*/
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
unsigned int nh_count = 0;
|
||||
unsigned int if_count = 0;
|
||||
unsigned int max_nh_if = 0;
|
||||
|
||||
STREAM_GETC(s, nexthop_num);
|
||||
zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
|
||||
nexthop_num);
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
label_type = lsp_type_from_re_type(client->proto);
|
||||
|
||||
for (i = 0; i < nexthop_num; i++) {
|
||||
STREAM_GETC(s, nexthop_type);
|
||||
|
||||
switch (nexthop_type) {
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
STREAM_GET(&nhop_addr, s, 16);
|
||||
if (nh_count < MULTIPATH_NUM) {
|
||||
/*
|
||||
* For labeled-unicast, each nexthop is
|
||||
* followed by label.
|
||||
*/
|
||||
if (CHECK_FLAG(message,
|
||||
ZAPI_MESSAGE_LABEL)) {
|
||||
STREAM_GETL(s, label);
|
||||
labels[nh_count] = label;
|
||||
}
|
||||
nexthops[nh_count++] = nhop_addr;
|
||||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
STREAM_GET(&nhop_addr, s, 16);
|
||||
STREAM_GETL(s, ifindex);
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nhop_addr, ifindex, re->vrf_id);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
if (if_count < multipath_num)
|
||||
STREAM_GETL(s, ifindices[if_count++]);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
default:
|
||||
zlog_warn(
|
||||
"%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
|
||||
__PRETTY_FUNCTION__);
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
max_nh_if = (nh_count > if_count) ? nh_count : if_count;
|
||||
for (i = 0; i < max_nh_if; i++) {
|
||||
if ((i < nh_count)
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
nexthop =
|
||||
route_entry_nexthop_ipv6_ifindex_add(
|
||||
re, &nexthops[i],
|
||||
ifindices[i],
|
||||
re->vrf_id);
|
||||
else
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
re, &nexthops[i], re->vrf_id);
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
|
||||
nexthop_add_labels(nexthop, label_type,
|
||||
1, &labels[i]);
|
||||
} else {
|
||||
if ((i < if_count) && ifindices[i])
|
||||
route_entry_nexthop_ifindex_add(
|
||||
re, ifindices[i], re->vrf_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Distance. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
|
||||
STREAM_GETC(s, re->distance);
|
||||
|
||||
/* Metric. */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
|
||||
STREAM_GETL(s, re->metric);
|
||||
|
||||
/* Tag */
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
|
||||
STREAM_GETL(s, re->tag);
|
||||
else
|
||||
re->tag = 0;
|
||||
|
||||
if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
|
||||
STREAM_GETL(s, re->mtu);
|
||||
else
|
||||
re->mtu = 0;
|
||||
|
||||
re->table = zvrf->table_id;
|
||||
|
||||
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);
|
||||
/* Stats */
|
||||
if (ret > 0)
|
||||
client->v6_route_add_cnt++;
|
||||
else if (ret < 0)
|
||||
client->v6_route_upd8_cnt++;
|
||||
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
nexthops_free(re->ng.nexthop);
|
||||
XFREE(MTYPE_RE, re);
|
||||
}
|
||||
|
||||
/* Zebra server IPv6 prefix delete function. */
|
||||
static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
struct zapi_ipv6 api;
|
||||
struct prefix p;
|
||||
struct prefix_ipv6 src_p, *src_pp;
|
||||
|
||||
s = msg;
|
||||
|
||||
/* Type, flags, message. */
|
||||
STREAM_GETC(s, api.type);
|
||||
STREAM_GETW(s, api.instance);
|
||||
STREAM_GETL(s, api.flags);
|
||||
STREAM_GETC(s, api.message);
|
||||
STREAM_GETW(s, api.safi);
|
||||
|
||||
/* IPv4 prefix. */
|
||||
memset(&p, 0, sizeof(struct prefix));
|
||||
p.family = AF_INET6;
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
|
||||
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
|
||||
memset(&src_p, 0, sizeof(struct prefix_ipv6));
|
||||
src_p.family = AF_INET6;
|
||||
STREAM_GETC(s, src_p.prefixlen);
|
||||
STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
|
||||
src_pp = &src_p;
|
||||
} else
|
||||
src_pp = NULL;
|
||||
|
||||
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||
api.flags, &p, src_pp, NULL, client->rtm_table, 0, 0, false);
|
||||
|
||||
client->v6_route_del_cnt++;
|
||||
|
||||
stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Register zebra server router-id information. Send current router-id */
|
||||
static void zread_router_id_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
@ -3011,11 +2410,6 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
|
||||
[ZEBRA_ROUTE_ADD] = zread_route_add,
|
||||
[ZEBRA_ROUTE_DELETE] = zread_route_del,
|
||||
[ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add,
|
||||
[ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete,
|
||||
[ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add,
|
||||
[ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add,
|
||||
[ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete,
|
||||
[ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
|
||||
[ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
|
||||
[ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
|
||||
|
@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
|
||||
|
||||
/* filter route selection in following order:
|
||||
* - connected beats other types
|
||||
* - if both connected, loopback or vrf wins
|
||||
* - lower distance beats higher
|
||||
* - lower metric beats higher for equal distance
|
||||
* - last, hence oldest, route wins tie break.
|
||||
*/
|
||||
|
||||
/* Connected routes. Pick the last connected
|
||||
/* Connected routes. Check to see if either are a vrf
|
||||
* or loopback interface. If not, pick the last connected
|
||||
* route of the set of lowest metric connected routes.
|
||||
*/
|
||||
if (alternate->type == ZEBRA_ROUTE_CONNECT) {
|
||||
if (current->type != ZEBRA_ROUTE_CONNECT
|
||||
|| alternate->metric <= current->metric)
|
||||
if (current->type != ZEBRA_ROUTE_CONNECT)
|
||||
return alternate;
|
||||
|
||||
/* both are connected. are either loop or vrf? */
|
||||
struct nexthop *nexthop = NULL;
|
||||
|
||||
for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
|
||||
if (if_is_loopback_or_vrf(if_lookup_by_index(
|
||||
nexthop->ifindex, alternate->vrf_id)))
|
||||
return alternate;
|
||||
}
|
||||
|
||||
for (ALL_NEXTHOPS(current->ng, nexthop)) {
|
||||
if (if_is_loopback_or_vrf(if_lookup_by_index(
|
||||
nexthop->ifindex, current->vrf_id)))
|
||||
return current;
|
||||
}
|
||||
|
||||
/* Neither are loop or vrf so pick best metric */
|
||||
if (alternate->metric <= current->metric)
|
||||
return alternate;
|
||||
|
||||
return current;
|
||||
@ -2651,8 +2671,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
}
|
||||
|
||||
/* Schedule routes of a particular table (address-family) based on event. */
|
||||
static void rib_update_table(struct route_table *table,
|
||||
rib_update_event_t event)
|
||||
void rib_update_table(struct route_table *table, rib_update_event_t event)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct route_entry *re, *next;
|
||||
@ -2732,12 +2751,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)
|
||||
|
||||
/* Process routes of interested address-families. */
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
|
||||
if (table)
|
||||
if (table) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP event %d", __func__, event);
|
||||
rib_update_table(table, event);
|
||||
}
|
||||
|
||||
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
|
||||
if (table)
|
||||
if (table) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP6 event %d", __func__, event);
|
||||
rib_update_table(table, event);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete self installed routes after zebra is relaunched. */
|
||||
|
@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
|
||||
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
|
||||
bool *exists)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
@ -119,6 +120,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
|
||||
prefix2str(p, buf, sizeof(buf));
|
||||
zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
|
||||
buf, type);
|
||||
exists = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -136,7 +138,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
|
||||
route_lock_node(rn);
|
||||
rn->info = rnh;
|
||||
rnh->node = rn;
|
||||
}
|
||||
*exists = false;
|
||||
} else
|
||||
*exists = true;
|
||||
|
||||
route_unlock_node(rn);
|
||||
return (rn->info);
|
||||
@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
|
||||
/*
|
||||
* This code will send to the registering client
|
||||
* the looked up rnh.
|
||||
* For a rnh that was created, there is no data
|
||||
* so it will send an empty nexthop group
|
||||
* If rnh exists then we know it has been evaluated
|
||||
* and as such it will have a resolved rnh.
|
||||
*/
|
||||
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
rnh_type_t type, vrf_id_t vrf_id)
|
||||
{
|
||||
@ -201,8 +213,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
}
|
||||
if (!listnode_lookup(rnh->client_list, client)) {
|
||||
listnode_add(rnh->client_list, client);
|
||||
send_client(rnh, client, type,
|
||||
vrf_id); // Pending: check if its needed
|
||||
send_client(rnh, client, type, vrf_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
|
||||
{
|
||||
struct prefix nh;
|
||||
struct rnh *rnh;
|
||||
bool exists;
|
||||
|
||||
addr2hostprefix(pw->af, &pw->nexthop, &nh);
|
||||
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE);
|
||||
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists);
|
||||
if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
|
||||
listnode_add(rnh->zebra_pseudowire_list, pw);
|
||||
pw->rnh = rnh;
|
||||
|
@ -68,7 +68,7 @@ static inline int rnh_resolve_via_default(int family)
|
||||
}
|
||||
|
||||
extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
rnh_type_t type);
|
||||
rnh_type_t type, bool *exists);
|
||||
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
rnh_type_t type);
|
||||
extern void zebra_free_rnh(struct rnh *rnh);
|
||||
|
@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
|
||||
/* `match ip address prefix-list PREFIX_LIST' */
|
||||
|
||||
static route_map_result_t
|
||||
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||
route_map_object_t type, void *object, afi_t afi)
|
||||
{
|
||||
struct prefix_list *plist;
|
||||
|
||||
if (type == RMAP_ZEBRA) {
|
||||
plist = prefix_list_lookup(AFI_IP, (char *)rule);
|
||||
plist = prefix_list_lookup(afi, (char *)rule);
|
||||
if (plist == NULL)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
static void *route_match_ip_address_prefix_list_compile(const char *arg)
|
||||
static route_map_result_t
|
||||
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
return (route_match_address_prefix_list(rule, prefix, type, object,
|
||||
AFI_IP));
|
||||
}
|
||||
|
||||
static void *route_match_address_prefix_list_compile(const char *arg)
|
||||
{
|
||||
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
|
||||
static void route_match_ip_address_prefix_list_free(void *rule)
|
||||
static void route_match_address_prefix_list_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
|
||||
"ip address prefix-list", route_match_ip_address_prefix_list,
|
||||
route_match_ip_address_prefix_list_compile,
|
||||
route_match_ip_address_prefix_list_free};
|
||||
route_match_address_prefix_list_compile,
|
||||
route_match_address_prefix_list_free};
|
||||
|
||||
static route_map_result_t
|
||||
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
return (route_match_address_prefix_list(rule, prefix, type, object,
|
||||
AFI_IP6));
|
||||
}
|
||||
|
||||
static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
|
||||
"ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
|
||||
route_match_address_prefix_list_compile,
|
||||
route_match_address_prefix_list_free};
|
||||
|
||||
/* `match ip address prefix-len PREFIXLEN' */
|
||||
|
||||
@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = {
|
||||
"src", route_set_src, route_set_src_compile, route_set_src_free,
|
||||
};
|
||||
|
||||
/* The function checks if the changed routemap specified by parameter rmap
|
||||
* matches the configured protocol routemaps in proto_rm table. If there is
|
||||
* a match then rib_update_table() to process the routes.
|
||||
*/
|
||||
static void zebra_rib_table_rm_update(const char *rmap)
|
||||
{
|
||||
int i = 0;
|
||||
struct route_table *table;
|
||||
char *rmap_name;
|
||||
char afi_ip = 0;
|
||||
char afi_ipv6 = 0;
|
||||
|
||||
for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
|
||||
/* Check for ip routemap table */
|
||||
rmap_name = proto_rm[AFI_IP][i];
|
||||
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP rmap %s, route type %s",
|
||||
__func__, rmap, zebra_route_string(i));
|
||||
/* There is single rib table for all protocols */
|
||||
if (afi_ip == 0) {
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST,
|
||||
VRF_DEFAULT);
|
||||
if (table) {
|
||||
afi_ip = 1;
|
||||
rib_update_table(table,
|
||||
RIB_UPDATE_RMAP_CHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for ipv6 routemap table */
|
||||
rmap_name = proto_rm[AFI_IP6][i];
|
||||
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP6 rmap %s,route type %s",
|
||||
__func__, rmap, zebra_route_string(i));
|
||||
if (afi_ipv6 == 0) {
|
||||
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST,
|
||||
VRF_DEFAULT);
|
||||
if (table) {
|
||||
afi_ipv6 = 1;
|
||||
rib_update_table(table,
|
||||
RIB_UPDATE_RMAP_CHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The function checks if the changed routemap specified by parameter rmap
|
||||
* matches the configured protocol routemaps in nht_rm table. If there is
|
||||
* a match then zebra_evaluate_rnh() to process the nexthops.
|
||||
*/
|
||||
static void zebra_nht_rm_update(const char *rmap)
|
||||
{
|
||||
int i = 0;
|
||||
char *rmap_name;
|
||||
char afi_ip = 0;
|
||||
char afi_ipv6 = 0;
|
||||
|
||||
for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
|
||||
rmap_name = nht_rm[AFI_IP][i];
|
||||
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP rmap %s route type %s",
|
||||
__func__, rmap, zebra_route_string(i));
|
||||
if (afi_ip == 0) {
|
||||
afi_ip = 1;
|
||||
zebra_evaluate_rnh(0, AF_INET, 1,
|
||||
RNH_NEXTHOP_TYPE, NULL);
|
||||
}
|
||||
}
|
||||
rmap_name = nht_rm[AFI_IP6][i];
|
||||
if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("%s : AFI_IP6 rmap %s route type %s",
|
||||
__func__, rmap, zebra_route_string(i));
|
||||
if (afi_ipv6 == 0) {
|
||||
afi_ipv6 = 1;
|
||||
zebra_evaluate_rnh(0, AF_INET6, 1,
|
||||
RNH_NEXTHOP_TYPE, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zebra_route_map_process_update_cb(char *rmap_name)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
zlog_debug("Event handler for route-map: %s",
|
||||
rmap_name);
|
||||
zebra_import_table_rm_update(rmap_name);
|
||||
zebra_rib_table_rm_update(rmap_name);
|
||||
zebra_nht_rm_update(rmap_name);
|
||||
}
|
||||
|
||||
static int zebra_route_map_update_timer(struct thread *thread)
|
||||
@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
|
||||
* 1) VRF Aware <sigh>
|
||||
* 2) Route-map aware
|
||||
*/
|
||||
zebra_import_table_rm_update();
|
||||
rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
|
||||
zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
|
||||
zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1555,12 +1660,19 @@ void zebra_route_map_init()
|
||||
route_map_match_tag_hook(generic_match_add);
|
||||
route_map_no_match_tag_hook(generic_match_delete);
|
||||
|
||||
route_map_match_ipv6_address_hook(generic_match_add);
|
||||
route_map_no_match_ipv6_address_hook(generic_match_delete);
|
||||
|
||||
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
|
||||
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
|
||||
|
||||
route_map_install_match(&route_match_tag_cmd);
|
||||
route_map_install_match(&route_match_interface_cmd);
|
||||
route_map_install_match(&route_match_ip_next_hop_cmd);
|
||||
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
|
||||
route_map_install_match(&route_match_ip_address_cmd);
|
||||
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
|
||||
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
|
||||
route_map_install_match(&route_match_ip_address_prefix_len_cmd);
|
||||
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
|
||||
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user