Merge remote-tracking 'frr/master' into SR-Routing

This commit is contained in:
Olivier Dugeon 2018-01-30 11:43:25 +01:00
commit dab8b7a81c
114 changed files with 2679 additions and 1211 deletions

View File

@ -57,3 +57,5 @@ ForEachMacros:
- SUBGRP_FOREACH_ADJ_SAFE
- AF_FOREACH
- FOREACH_AFI_SAFI
# ospfd
- LSDB_LOOP

12
README
View File

@ -1,12 +1,14 @@
FRRouting is free software that manages various IPv4 and IPv6 routing
protocols.
FRRouting is free software that implements and manages various IPv4 and IPv6
routing protocols.
Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1,
RIPv2, RIPng, PIM-SM/MSDP and LDP as well as very early support for IS-IS,
EIGRP and NHRP.
Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng,
IS-IS, PIM-SM/MSDP, LDP and Babel as well as very early support for EIGRP and
NHRP.
See the file REPORTING-BUGS to report bugs.
See COMMUNITY.md for information on contributing.
Free RRRouting is free software. See the file COPYING for copying conditions.
Public email discussion can be found at https://lists.frrouting.org/listinfo

View File

@ -166,6 +166,7 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
api.type = ZEBRA_ROUTE_BABEL;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = quagga_prefix;
if(metric >= KERNEL_INFINITY) {

View File

@ -246,8 +246,6 @@ void bgp_sync_init(struct peer *peer)
BGP_ADV_FIFO_INIT(&sync->withdraw);
BGP_ADV_FIFO_INIT(&sync->withdraw_low);
peer->sync[afi][safi] = sync;
peer->hash[afi][safi] = hash_create(baa_hash_key, baa_hash_cmp,
"BGP Sync Hash");
}
}
@ -260,9 +258,5 @@ void bgp_sync_delete(struct peer *peer)
if (peer->sync[afi][safi])
XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL;
if (peer->hash[afi][safi])
hash_free(peer->hash[afi][safi]);
peer->hash[afi][safi] = NULL;
}
}

View File

@ -302,13 +302,13 @@ static int bgp_bfd_dest_update(int command, struct zclient *zclient,
prefix2str(&dp, buf[0], sizeof(buf[0]));
if (ifp) {
zlog_debug(
"Zebra: vrf %d interface %s bfd destination %s %s",
"Zebra: vrf %u interface %s bfd destination %s %s",
vrf_id, ifp->name, buf[0],
bfd_get_status_str(status));
} else {
prefix2str(&sp, buf[1], sizeof(buf[1]));
zlog_debug(
"Zebra: vrf %d source %s bfd destination %s %s",
"Zebra: vrf %u source %s bfd destination %s %s",
vrf_id, buf[1], buf[0],
bfd_get_status_str(status));
}

View File

@ -51,74 +51,13 @@ static bool validate_header(struct peer *);
#define BGP_IO_TRANS_ERR (1 << 0) // EAGAIN or similar occurred
#define BGP_IO_FATAL_ERR (1 << 1) // some kind of fatal TCP error
/* Start and stop routines for I/O pthread + control variables
* ------------------------------------------------------------------------ */
_Atomic bool bgp_io_thread_run;
_Atomic bool bgp_io_thread_started;
void bgp_io_init()
{
bgp_io_thread_run = false;
bgp_io_thread_started = false;
}
/* Unused callback for thread_add_read() */
static int bgp_io_dummy(struct thread *thread) { return 0; }
void *bgp_io_start(void *arg)
{
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
fpt->master->owner = pthread_self();
// fd so we can sleep in poll()
int sleeper[2];
pipe(sleeper);
thread_add_read(fpt->master, &bgp_io_dummy, NULL, sleeper[0], NULL);
// we definitely don't want to handle signals
fpt->master->handle_signals = false;
struct thread task;
atomic_store_explicit(&bgp_io_thread_run, true, memory_order_seq_cst);
atomic_store_explicit(&bgp_io_thread_started, true,
memory_order_seq_cst);
while (bgp_io_thread_run) {
if (thread_fetch(fpt->master, &task)) {
thread_call(&task);
}
}
close(sleeper[1]);
close(sleeper[0]);
return NULL;
}
static int bgp_io_finish(struct thread *thread)
{
atomic_store_explicit(&bgp_io_thread_run, false, memory_order_seq_cst);
return 0;
}
int bgp_io_stop(void **result, struct frr_pthread *fpt)
{
thread_add_event(fpt->master, &bgp_io_finish, NULL, 0, NULL);
pthread_join(fpt->thread, result);
return 0;
}
/* Extern API -------------------------------------------------------------- */
void bgp_io_running(void)
{
while (!atomic_load_explicit(&bgp_io_thread_started,
memory_order_seq_cst))
frr_pthread_yield();
}
/* Thread external API ----------------------------------------------------- */
void bgp_writes_on(struct peer *peer)
{
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
assert(peer->status != Deleted);
assert(peer->obuf);
assert(peer->ibuf);
@ -127,8 +66,6 @@ void bgp_writes_on(struct peer *peer)
assert(!peer->t_connect_check_w);
assert(peer->fd);
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
thread_add_write(fpt->master, bgp_process_writes, peer, peer->fd,
&peer->t_write);
SET_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON);
@ -137,6 +74,7 @@ void bgp_writes_on(struct peer *peer)
void bgp_writes_off(struct peer *peer)
{
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
thread_cancel_async(fpt->master, &peer->t_write, NULL);
THREAD_OFF(peer->t_generate_updgrp_packets);
@ -146,6 +84,9 @@ void bgp_writes_off(struct peer *peer)
void bgp_reads_on(struct peer *peer)
{
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
assert(peer->status != Deleted);
assert(peer->ibuf);
assert(peer->fd);
@ -155,8 +96,6 @@ void bgp_reads_on(struct peer *peer)
assert(!peer->t_connect_check_w);
assert(peer->fd);
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
&peer->t_read);
@ -166,6 +105,7 @@ void bgp_reads_on(struct peer *peer)
void bgp_reads_off(struct peer *peer)
{
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
thread_cancel_async(fpt->master, &peer->t_read, NULL);
THREAD_OFF(peer->t_process_packet);
@ -173,9 +113,9 @@ void bgp_reads_off(struct peer *peer)
UNSET_FLAG(peer->thread_flags, PEER_THREAD_READS_ON);
}
/* Internal functions ------------------------------------------------------- */
/* Thread internal functions ----------------------------------------------- */
/**
/*
* Called from I/O pthread when a file descriptor has become ready for writing.
*/
static int bgp_process_writes(struct thread *thread)
@ -198,11 +138,13 @@ static int bgp_process_writes(struct thread *thread)
}
pthread_mutex_unlock(&peer->io_mtx);
if (CHECK_FLAG(status, BGP_IO_TRANS_ERR)) { /* no problem */
/* no problem */
if (CHECK_FLAG(status, BGP_IO_TRANS_ERR)) {
}
/* problem */
if (CHECK_FLAG(status, BGP_IO_FATAL_ERR)) {
reschedule = false; /* problem */
reschedule = false;
fatal = true;
}
@ -217,7 +159,7 @@ static int bgp_process_writes(struct thread *thread)
return 0;
}
/**
/*
* Called from I/O pthread when a file descriptor has become ready for reading,
* or has hung up.
*
@ -288,8 +230,10 @@ static int bgp_process_reads(struct thread *thread)
/* if this fails we are seriously screwed */
assert(pktsize <= BGP_MAX_PACKET_SIZE);
/* If we have that much data, chuck it into its own
* stream and append to input queue for processing. */
/*
* If we have that much data, chuck it into its own
* stream and append to input queue for processing.
*/
if (ringbuf_remain(ibw) >= pktsize) {
struct stream *pkt = stream_new(pktsize);
assert(ringbuf_get(ibw, pktbuf, pktsize) == pktsize);
@ -323,7 +267,7 @@ static int bgp_process_reads(struct thread *thread)
return 0;
}
/**
/*
* Flush peer output buffer.
*
* This function pops packets off of peer->obuf and writes them to peer->fd.
@ -342,15 +286,10 @@ static uint16_t bgp_write(struct peer *peer)
int num;
int update_last_write = 0;
unsigned int count = 0;
uint32_t oc;
uint32_t uo;
uint32_t uo = 0;
uint16_t status = 0;
uint32_t wpkt_quanta_old;
// save current # updates sent
oc = atomic_load_explicit(&peer->update_out, memory_order_relaxed);
// cache current write quanta
wpkt_quanta_old =
atomic_load_explicit(&peer->bgp->wpkt_quanta, memory_order_relaxed);
@ -369,7 +308,7 @@ static uint16_t bgp_write(struct peer *peer)
}
goto done;
} else if (num != writenum) // incomplete write
} else if (num != writenum)
stream_forward_getp(s, num);
} while (num != writenum);
@ -386,6 +325,7 @@ static uint16_t bgp_write(struct peer *peer)
case BGP_MSG_UPDATE:
atomic_fetch_add_explicit(&peer->update_out, 1,
memory_order_relaxed);
uo++;
break;
case BGP_MSG_NOTIFY:
atomic_fetch_add_explicit(&peer->notify_out, 1,
@ -397,8 +337,10 @@ static uint16_t bgp_write(struct peer *peer)
if (peer->v_start >= (60 * 2))
peer->v_start = (60 * 2);
/* Handle Graceful Restart case where the state changes
* to Connect instead of Idle */
/*
* Handle Graceful Restart case where the state changes
* to Connect instead of Idle.
*/
BGP_EVENT_ADD(peer, BGP_Stop);
goto done;
@ -424,9 +366,12 @@ static uint16_t bgp_write(struct peer *peer)
}
done : {
/* Update last_update if UPDATEs were written. */
uo = atomic_load_explicit(&peer->update_out, memory_order_relaxed);
if (uo > oc)
/*
* Update last_update if UPDATEs were written.
* Note: that these are only updated at end,
* not per message (i.e., per loop)
*/
if (uo)
atomic_store_explicit(&peer->last_update, bgp_clock(),
memory_order_relaxed);
@ -439,7 +384,7 @@ done : {
return status;
}
/**
/*
* Reads a chunk of data from peer->fd into peer->ibuf_work.
*
* @return status flag (see top-of-file)

View File

@ -28,24 +28,6 @@
#include "bgpd/bgpd.h"
#include "frr_pthread.h"
/**
* Initializes data structures and flags for the write thread.
*
* This function should be called from the main thread before
* bgp_writes_start() is invoked.
*/
extern void bgp_io_init(void);
/**
* Ensure that the BGP IO thread is actually up and running
*
* This function must be called immediately after the thread
* has been created for running. This is because we want
* to make sure that the io thread is ready before other
* threads start attempting to use it.
*/
extern void bgp_io_running(void);
/**
* Start function for write thread.
*

View File

@ -36,14 +36,14 @@
#include "bgpd/bgp_keepalives.h"
/* clang-format on */
/**
/*
* Peer KeepAlive Timer.
* Associates a peer with the time of its last keepalive.
*/
struct pkat {
// the peer to send keepalives to
/* the peer to send keepalives to */
struct peer *peer;
// absolute time of last keepalive sent
/* absolute time of last keepalive sent */
struct timeval last;
};
@ -52,9 +52,6 @@ static pthread_mutex_t *peerhash_mtx;
static pthread_cond_t *peerhash_cond;
static struct hash *peerhash;
/* Thread control flag. */
bool bgp_keepalives_thread_run = false;
static struct pkat *pkat_new(struct peer *peer)
{
struct pkat *pkat = XMALLOC(MTYPE_TMP, sizeof(struct pkat));
@ -100,10 +97,10 @@ static void peer_process(struct hash_backet *hb, void *arg)
static struct timeval tolerance = {0, 100000};
// calculate elapsed time since last keepalive
/* calculate elapsed time since last keepalive */
monotime_since(&pkat->last, &elapsed);
// calculate difference between elapsed time and configured time
/* calculate difference between elapsed time and configured time */
ka.tv_sec = pkat->peer->v_keepalive;
timersub(&ka, &elapsed, &diff);
@ -118,10 +115,10 @@ static void peer_process(struct hash_backet *hb, void *arg)
bgp_keepalive_send(pkat->peer);
monotime(&pkat->last);
memset(&elapsed, 0x00, sizeof(struct timeval));
diff = ka; // time until next keepalive == peer keepalive time
diff = ka;
}
// if calculated next update for this peer < current delay, use it
/* if calculated next update for this peer < current delay, use it */
if (next_update->tv_sec <= 0 || timercmp(&diff, next_update, <))
*next_update = diff;
}
@ -139,29 +136,9 @@ static unsigned int peer_hash_key(void *arg)
return (uintptr_t)pkat->peer;
}
void bgp_keepalives_init()
{
peerhash_mtx = XCALLOC(MTYPE_TMP, sizeof(pthread_mutex_t));
peerhash_cond = XCALLOC(MTYPE_TMP, sizeof(pthread_cond_t));
// initialize mutex
pthread_mutex_init(peerhash_mtx, NULL);
// use monotonic clock with condition variable
pthread_condattr_t attrs;
pthread_condattr_init(&attrs);
pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
pthread_cond_init(peerhash_cond, &attrs);
pthread_condattr_destroy(&attrs);
// initialize peer hashtable
peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL);
}
/* Cleanup handler / deinitializer. */
static void bgp_keepalives_finish(void *arg)
{
bgp_keepalives_thread_run = false;
if (peerhash) {
hash_clean(peerhash, pkat_del);
hash_free(peerhash);
@ -177,32 +154,50 @@ static void bgp_keepalives_finish(void *arg)
XFREE(MTYPE_TMP, peerhash_cond);
}
/**
/*
* Entry function for peer keepalive generation pthread.
*
* bgp_keepalives_init() must be called prior to this.
*/
void *bgp_keepalives_start(void *arg)
{
struct frr_pthread *fpt = arg;
fpt->master->owner = pthread_self();
struct timeval currtime = {0, 0};
struct timeval aftertime = {0, 0};
struct timeval next_update = {0, 0};
struct timespec next_update_ts = {0, 0};
peerhash_mtx = XCALLOC(MTYPE_TMP, sizeof(pthread_mutex_t));
peerhash_cond = XCALLOC(MTYPE_TMP, sizeof(pthread_cond_t));
/* initialize mutex */
pthread_mutex_init(peerhash_mtx, NULL);
/* use monotonic clock with condition variable */
pthread_condattr_t attrs;
pthread_condattr_init(&attrs);
pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
pthread_cond_init(peerhash_cond, &attrs);
pthread_condattr_destroy(&attrs);
/* initialize peer hashtable */
peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL);
pthread_mutex_lock(peerhash_mtx);
// register cleanup handler
/* register cleanup handler */
pthread_cleanup_push(&bgp_keepalives_finish, NULL);
bgp_keepalives_thread_run = true;
/* notify anybody waiting on us that we are done starting up */
frr_pthread_notify_running(fpt);
while (bgp_keepalives_thread_run) {
while (atomic_load_explicit(&fpt->running, memory_order_relaxed)) {
if (peerhash->count > 0)
pthread_cond_timedwait(peerhash_cond, peerhash_mtx,
&next_update_ts);
else
while (peerhash->count == 0
&& bgp_keepalives_thread_run)
&& atomic_load_explicit(&fpt->running,
memory_order_relaxed))
pthread_cond_wait(peerhash_cond, peerhash_mtx);
monotime(&currtime);
@ -219,7 +214,7 @@ void *bgp_keepalives_start(void *arg)
TIMEVAL_TO_TIMESPEC(&next_update, &next_update_ts);
}
// clean up
/* clean up */
pthread_cleanup_pop(1);
return NULL;
@ -229,6 +224,12 @@ void *bgp_keepalives_start(void *arg)
void bgp_keepalives_on(struct peer *peer)
{
if (CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON))
return;
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_KEEPALIVES);
assert(fpt->running);
/* placeholder bucket data to use for fast key lookups */
static struct pkat holder = {0};
@ -253,6 +254,12 @@ void bgp_keepalives_on(struct peer *peer)
void bgp_keepalives_off(struct peer *peer)
{
if (!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON))
return;
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_KEEPALIVES);
assert(fpt->running);
/* placeholder bucket data to use for fast key lookups */
static struct pkat holder = {0};
@ -283,10 +290,13 @@ void bgp_keepalives_wake()
pthread_mutex_unlock(peerhash_mtx);
}
int bgp_keepalives_stop(void **result, struct frr_pthread *fpt)
int bgp_keepalives_stop(struct frr_pthread *fpt, void **result)
{
bgp_keepalives_thread_run = false;
assert(fpt->running);
atomic_store_explicit(&fpt->running, false, memory_order_relaxed);
bgp_keepalives_wake();
pthread_join(fpt->thread, result);
return 0;
}

View File

@ -88,6 +88,6 @@ extern void bgp_keepalives_wake(void);
/**
* Stops the thread and blocks until it terminates.
*/
int bgp_keepalives_stop(void **result, struct frr_pthread *fpt);
int bgp_keepalives_stop(struct frr_pthread *fpt, void **result);
#endif /* _FRR_BGP_KEEPALIVES_H */

View File

@ -232,7 +232,7 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
static int bgp_vrf_new(struct vrf *vrf)
{
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
return 0;
}
@ -240,7 +240,7 @@ static int bgp_vrf_new(struct vrf *vrf)
static int bgp_vrf_delete(struct vrf *vrf)
{
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
return 0;
}
@ -251,7 +251,7 @@ static int bgp_vrf_enable(struct vrf *vrf)
vrf_id_t old_vrf_id;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id);
zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
bgp = bgp_lookup_by_name(vrf->name);
if (bgp) {

View File

@ -336,7 +336,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) {
zlog_err(
"parse nexthop update: instance not found for vrf_id %d",
"parse nexthop update: instance not found for vrf_id %u",
vrf_id);
return;
}
@ -389,7 +389,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf));
zlog_debug(
"%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
"%u: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
vrf_id, buf, metric, bnc->metric, nexthop_num,
bnc->nexthop_num, bnc->flags);
}
@ -572,12 +572,11 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
*/
static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
{
struct stream *s;
struct prefix *p;
bool exact_match = false;
int ret;
/* Check socket. */
if (!zclient || zclient->sock < 0)
if (!zclient)
return;
/* Don't try to register if Zebra doesn't know of this instance. */
@ -585,32 +584,14 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
return;
p = &(bnc->node->p);
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, command, bnc->bgp->vrf_id);
if ((command == ZEBRA_NEXTHOP_REGISTER ||
command == ZEBRA_IMPORT_ROUTE_REGISTER) &&
(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
|| CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
stream_putc(s, 1);
else
stream_putc(s, 0);
exact_match = true;
stream_putw(s, PREFIX_FAMILY(p));
stream_putc(s, p->prefixlen);
switch (PREFIX_FAMILY(p)) {
case AF_INET:
stream_put_in_addr(s, &p->u.prefix4);
break;
case AF_INET6:
stream_put(s, &(p->u.prefix6), 16);
break;
default:
break;
}
stream_putw_at(s, 0, stream_get_endp(s));
ret = zclient_send_message(zclient);
ret = zclient_send_rnh(zclient, command, p,
exact_match, bnc->bgp->vrf_id);
/* TBD: handle the failure */
if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed");

View File

@ -545,19 +545,26 @@ void bgp_open_send(struct peer *peer)
bgp_writes_on(peer);
}
/* This is only for sending NOTIFICATION message to neighbor. */
/*
* Writes NOTIFICATION message directly to a peer socket without waiting for
* the I/O thread.
*
* There must be exactly one stream on the peer->obuf FIFO, and the data within
* this stream must match the format of a BGP NOTIFICATION message.
* Transmission is best-effort.
*
* @requires peer->io_mtx
* @param peer
* @return 0
*/
static int bgp_write_notify(struct peer *peer)
{
int ret, val;
u_char type;
struct stream *s;
pthread_mutex_lock(&peer->io_mtx);
{
/* There should be at least one packet. */
s = stream_fifo_pop(peer->obuf);
}
pthread_mutex_unlock(&peer->io_mtx);
if (!s)
return 0;
@ -622,6 +629,14 @@ static int bgp_write_notify(struct peer *peer)
* This function attempts to write the packet from the thread it is called
* from, to ensure the packet gets out ASAP.
*
* This function may be called from multiple threads. Since the function
* modifies I/O buffer(s) in the peer, these are locked for the duration of the
* call to prevent tampering from other threads.
*
* Delivery of the NOTIFICATION is attempted once and is best-effort. After
* return, the peer structure *must* be reset; no assumptions about session
* state are valid.
*
* @param peer
* @param code BGP error code
* @param sub_code BGP error subcode
@ -634,6 +649,10 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
struct stream *s;
int length;
/* Lock I/O mutex to prevent other threads from pushing packets */
pthread_mutex_lock(&peer->io_mtx);
/* ============================================== */
/* Allocate new stream. */
s = stream_new(BGP_MAX_PACKET_SIZE);
@ -651,20 +670,8 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
/* Set BGP packet length. */
length = bgp_packet_set_size(s);
/*
* Turn off keepalive generation for peer. This is necessary because
* otherwise between the time we wipe the output buffer and the time we
* push the NOTIFY onto it, the KA generation thread could have pushed
* a KEEPALIVE in the middle.
*/
bgp_keepalives_off(peer);
/* wipe output buffer */
pthread_mutex_lock(&peer->io_mtx);
{
stream_fifo_clean(peer->obuf);
}
pthread_mutex_unlock(&peer->io_mtx);
/*
* If possible, store last packet for debugging purposes. This check is
@ -728,9 +735,12 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
/* Add packet to peer's output queue */
bgp_packet_add(peer, s);
stream_fifo_push(peer->obuf, s);
bgp_write_notify(peer);
/* ============================================== */
pthread_mutex_unlock(&peer->io_mtx);
}
/*

View File

@ -2719,7 +2719,9 @@ int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
/* AS path local-as loop check. */
if (peer->change_local_as) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
if (peer->allowas_in[afi][safi])
aspath_loop_count = peer->allowas_in[afi][safi];
else if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
aspath_loop_count = 1;
if (aspath_loop_check(attr->aspath, peer->change_local_as)
@ -7857,7 +7859,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
vty_out(vty,
"{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"routes\": { ",
bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id,
bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
: bgp->name,
table->version, inet_ntoa(bgp->router_id));
@ -8125,6 +8127,9 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
struct bgp_node *rn, *next;
unsigned long output_cum = 0;
unsigned long total_cum = 0;
bool show_msg;
show_msg = (!use_json && type == bgp_show_type_normal);
for (rn = bgp_table_top(table); rn; rn = next) {
next = bgp_route_next(rn);
@ -8140,8 +8145,19 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
output_arg, use_json,
rd, next == NULL,
&output_cum, &total_cum);
if (next == NULL)
show_msg = false;
}
}
if (show_msg) {
if (output_cum == 0)
vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
total_cum);
else
vty_out(vty,
"\nDisplayed %ld routes and %ld total paths\n",
output_cum, total_cum);
}
if (use_json)
vty_out(vty, " } }");
return CMD_SUCCESS;
@ -10902,7 +10918,7 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
&bgp_static->gatewayIp.u.prefix, buf2,
sizeof(buf2));
vty_out(vty,
" network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
" network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
buf, rdbuf, p->u.prefix_evpn.eth_tag,
decode_label(&bgp_static->label), esi, buf2,
macrouter);

View File

@ -2692,6 +2692,19 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
return bgp_vty_return(vty, ret);
}
DEFUN (bgp_default_shutdown,
bgp_default_shutdown_cmd,
"[no] bgp default shutdown",
NO_STR
BGP_STR
"Configure BGP defaults\n"
"Do not automatically activate peers upon configuration\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp->autoshutdown = !strmatch(argv[0]->text, "no");
return CMD_SUCCESS;
}
DEFUN (neighbor_remote_as,
neighbor_remote_as_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <(1-4294967295)|internal|external>",
@ -3238,7 +3251,6 @@ DEFUN (no_neighbor_password,
return bgp_vty_return(vty, ret);
}
DEFUN (neighbor_activate,
neighbor_activate_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> activate",
@ -6490,7 +6502,6 @@ DEFUN (show_bgp_vrfs,
struct listnode *node, *nnode;
int peers_cfg, peers_estb;
json_object *json_vrf = NULL;
int vrf_id_ui;
/* Skip Views. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
@ -6524,8 +6535,10 @@ DEFUN (show_bgp_vrfs,
type = "VRF";
}
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id;
if (uj) {
int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 :
(int64_t)bgp->vrf_id;
json_object_string_add(json_vrf, "type", type);
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
json_object_string_add(json_vrf, "routerId",
@ -6543,7 +6556,9 @@ DEFUN (show_bgp_vrfs,
} else
vty_out(vty,
"%4s %-5d %-16s %9u %10u %-37s %-10u %-15s\n",
type, vrf_id_ui, inet_ntoa(bgp->router_id),
type, bgp->vrf_id == VRF_UNKNOWN ?
-1 : (int)bgp->vrf_id,
inet_ntoa(bgp->router_id),
peers_cfg, peers_estb, name, bgp->l3vni,
prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
}
@ -6863,10 +6878,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (!count) {
unsigned long ents;
char memstrbuf[MTYPE_MEMSTR_LEN];
int vrf_id_ui;
int64_t vrf_id_ui;
vrf_id_ui =
(bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id;
(bgp->vrf_id == VRF_UNKNOWN) ? -1 :
(int64_t)bgp->vrf_id;
/* Usage summary and header */
if (use_json) {
@ -6885,7 +6901,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
vty_out(vty,
"BGP router identifier %s, local AS number %u vrf-id %d",
inet_ntoa(bgp->router_id), bgp->as,
vrf_id_ui);
bgp->vrf_id == VRF_UNKNOWN ? -1 :
(int)bgp->vrf_id);
vty_out(vty, "\n");
}
@ -9853,7 +9870,6 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
}
if (use_json) {
bgp_show_bestpath_json(bgp, json);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
@ -9887,8 +9903,7 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
json_object_int_add(json, "vrfId",
(bgp->vrf_id == VRF_UNKNOWN)
? -1
: bgp->vrf_id);
? -1 : (int64_t) bgp->vrf_id);
json_object_string_add(
json, "vrfName",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
@ -11578,6 +11593,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_listen_range_cmd);
install_element(BGP_NODE, &no_bgp_listen_range_cmd);
/* "neighbors auto-shutdown" command */
install_element(BGP_NODE, &bgp_default_shutdown_cmd);
/* "neighbor remote-as" commands. */
install_element(BGP_NODE, &neighbor_remote_as_cmd);
install_element(BGP_NODE, &neighbor_interface_config_cmd);

View File

@ -1001,6 +1001,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.nh_vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
@ -1253,6 +1254,7 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = peer->bgp->vrf_id;
api.nh_vrf_id = peer->bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;

View File

@ -866,8 +866,7 @@ static void peer_af_flag_reset(struct peer *peer, afi_t afi, safi_t safi)
/* peer global config reset */
static void peer_global_config_reset(struct peer *peer)
{
int v6only;
int saved_flags = 0;
peer->change_local_as = 0;
peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1);
@ -885,13 +884,11 @@ static void peer_global_config_reset(struct peer *peer)
else
peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
/* This is a per-peer specific flag and so we must preserve it */
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
/* These are per-peer specific flags and so we must preserve them */
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN);
peer->flags = 0;
if (v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
SET_FLAG(peer->flags, saved_flags);
peer->config = 0;
peer->holdtime = 0;
@ -1498,8 +1495,11 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
peer_af_create(peer, afi, safi);
}
/* auto shutdown if configured */
if (bgp->autoshutdown)
peer_flag_set(peer, PEER_FLAG_SHUTDOWN);
/* Set up peer's events and timers. */
if (!active && peer_active(peer))
else if (!active && peer_active(peer))
bgp_timer_set(peer);
return peer;
@ -2340,7 +2340,7 @@ static void peer_group2peer_config_copy(struct peer_group *group,
struct peer *peer)
{
struct peer *conf;
int v6only;
int saved_flags = 0;
conf = group->conf;
@ -2358,14 +2358,11 @@ static void peer_group2peer_config_copy(struct peer_group *group,
/* GTSM hops */
peer->gtsm_hops = conf->gtsm_hops;
/* this flag is per-neighbor and so has to be preserved */
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
/* peer flags apply */
/* These are per-peer specific flags and so we must preserve them */
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN);
peer->flags = conf->flags;
if (v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
SET_FLAG(peer->flags, saved_flags);
/* peer config apply */
peer->config = conf->config;
@ -7152,6 +7149,10 @@ int bgp_config_write(struct vty *vty)
vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
bgp->default_subgroup_pkt_queue_max);
/* BGP default autoshutdown neighbors */
if (bgp->autoshutdown)
vty_out(vty, " bgp default auto-shutdown\n");
/* BGP client-to-client reflection. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
vty_out(vty, " no bgp client-to-client reflection\n");
@ -7469,32 +7470,33 @@ static void bgp_pthreads_init()
{
frr_pthread_init();
frr_pthread_new("BGP i/o thread", PTHREAD_IO, bgp_io_start,
bgp_io_stop);
frr_pthread_new("BGP keepalives thread", PTHREAD_KEEPALIVES,
bgp_keepalives_start, bgp_keepalives_stop);
/* pre-run initialization */
bgp_keepalives_init();
bgp_io_init();
struct frr_pthread_attr io = {
.id = PTHREAD_IO,
.start = frr_pthread_attr_default.start,
.stop = frr_pthread_attr_default.stop,
.name = "BGP I/O thread",
};
struct frr_pthread_attr ka = {
.id = PTHREAD_KEEPALIVES,
.start = bgp_keepalives_start,
.stop = bgp_keepalives_stop,
.name = "BGP Keepalives thread",
};
frr_pthread_new(&io);
frr_pthread_new(&ka);
}
void bgp_pthreads_run()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
struct frr_pthread *io = frr_pthread_get(PTHREAD_IO);
struct frr_pthread *ka = frr_pthread_get(PTHREAD_KEEPALIVES);
/*
* Please ensure that the io thread is running
* by calling bgp_io_running. The BGP threads
* depend on it being running when we start
* looking for it.
*/
frr_pthread_run(PTHREAD_IO, &attr, NULL);
bgp_io_running();
frr_pthread_run(io, NULL);
frr_pthread_run(ka, NULL);
frr_pthread_run(PTHREAD_KEEPALIVES, &attr, NULL);
/* Wait until threads are ready. */
frr_pthread_wait_running(io);
frr_pthread_wait_running(ka);
}
void bgp_pthreads_finish()

View File

@ -390,6 +390,9 @@ struct bgp {
/* Actual coalesce time */
uint32_t coalesce_time;
/* Auto-shutdown new peers */
bool autoshutdown;
u_int32_t addpath_tx_id;
int addpath_tx_used[AFI_MAX][SAFI_MAX];
@ -916,9 +919,6 @@ struct peer {
/* Send prefix count. */
unsigned long scount[AFI_MAX][SAFI_MAX];
/* Announcement attribute hash. */
struct hash *hash[AFI_MAX][SAFI_MAX];
/* Notify data. */
struct bgp_notify notify;

View File

@ -913,7 +913,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
* aspath: points to interned hash from aspath hash table
*/
red = bgp_redist_lookup(bgp, afi, type, VRF_DEFAULT);
red = bgp_redist_lookup(bgp, afi, type, 0);
if (red && red->redist_metric_flag) {
attr.med = red->redist_metric;

View File

@ -385,6 +385,8 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
struct zapi_route api;
struct zapi_nexthop *api_nh;
int i;
struct in_addr **nhp_ary4 = nhp_ary;
struct in6_addr **nhp_ary6 = nhp_ary;
if (!nhp_count) {
vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
@ -394,6 +396,7 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC;
api.safi = SAFI_UNICAST;
api.prefix = *p;
@ -402,20 +405,16 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = MIN(nhp_count, multipath_num);
for (i = 0; i < api.nexthop_num; i++) {
struct in_addr *nhp_ary4;
struct in6_addr *nhp_ary6;
api_nh = &api.nexthops[i];
switch (p->family) {
case AF_INET:
nhp_ary4 = nhp_ary;
memcpy(&api_nh->gate.ipv4, &nhp_ary4[i],
memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
sizeof(api_nh->gate.ipv4));
api_nh->type = NEXTHOP_TYPE_IPV4;
break;
case AF_INET6:
nhp_ary6 = nhp_ary;
memcpy(&api_nh->gate.ipv6, &nhp_ary6[i],
memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
sizeof(api_nh->gate.ipv6));
api_nh->type = NEXTHOP_TYPE_IPV6;
break;

View File

@ -823,22 +823,15 @@ Network Layer protocols. BGP supports multiple Address Family
Identifier (AFI), namely IPv4 and IPv6. Support is also provided for
multiple sets of per-AFI information via Subsequent Address Family
Identifiers (SAFI). In addition to unicast information, VPN information
@cite{RFC4364} and @cite{RFC4659}, and Encapsulation information
@cite{RFC4364} and @cite{RFC4659}, and Encapsulation attribute
@cite{RFC5512} is supported.
@deffn {Command} {show ip bgp vpnv4 all} {}
@deffnx {Command} {show ipv6 bgp vpn all} {}
@deffn {Command} {show ip bgp ipv4 vpn} {}
@deffnx {Command} {show ipv6 bgp ipv6 vpn} {}
Print active IPV4 or IPV6 routes advertised via the VPN SAFI.
@end deffn
@deffn {Command} {show ip bgp encap all} {}
@deffnx {Command} {show ipv6 bgp encap all} {}
Print active IPV4 or IPV6 routes advertised via the Encapsulation SAFI.
@end deffn
@deffn {Command} {show bgp ipv4 encap summary} {}
@deffnx {Command} {show bgp ipv4 vpn summary} {}
@deffnx {Command} {show bgp ipv6 encap summary} {}
@deffn {Command} {show bgp ipv4 vpn summary} {}
@deffnx {Command} {show bgp ipv6 vpn summary} {}
Print a summary of neighbor connections for the specified AFI/SAFI combination.
@end deffn

View File

@ -373,36 +373,37 @@ log file /var/log/zebra.log
!
interface eth0
ip address 10.2.2.2/24
mpls-te on
mpls-te link metric 10
mpls-te link max-bw 1.25e+06
mpls-te link max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06
mpls-te link rsc-clsclr 0xab
link-params
enable
metric 100
max-bw 1.25e+07
max-rsv-bw 1.25e+06
unrsv-bw 0 1.25e+06
unrsv-bw 1 1.25e+06
unrsv-bw 2 1.25e+06
unrsv-bw 3 1.25e+06
unrsv-bw 4 1.25e+06
unrsv-bw 5 1.25e+06
unrsv-bw 6 1.25e+06
unrsv-bw 7 1.25e+06
admin-grp 0xab
!
interface eth1
ip address 10.1.1.1/24
mpls-te on
mpls-te link metric 10
mpls-te link max-bw 1.25e+06
mpls-te link max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06
mpls-te link rsc-clsclr 0xab
mpls-te neighbor 10.1.1.2 as 65000
link-params
enable
metric 100
max-bw 1.25e+07
max-rsv-bw 1.25e+06
unrsv-bw 0 1.25e+06
unrsv-bw 1 1.25e+06
unrsv-bw 2 1.25e+06
unrsv-bw 3 1.25e+06
unrsv-bw 4 1.25e+06
unrsv-bw 5 1.25e+06
unrsv-bw 6 1.25e+06
unrsv-bw 7 1.25e+06
neighbor 10.1.1.2 as 65000
@end group
@end example

View File

@ -884,36 +884,37 @@ log file /var/log/zebra.log
!
interface eth0
ip address 198.168.1.1/24
mpls-te on
mpls-te link metric 10
mpls-te link max-bw 1.25e+06
mpls-te link max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06
mpls-te link rsc-clsclr 0xab
link-params
enable
admin-grp 0xa1
metric 100
max-bw 1.25e+07
max-rsv-bw 1.25e+06
unrsv-bw 0 1.25e+06
unrsv-bw 1 1.25e+06
unrsv-bw 2 1.25e+06
unrsv-bw 3 1.25e+06
unrsv-bw 4 1.25e+06
unrsv-bw 5 1.25e+06
unrsv-bw 6 1.25e+06
unrsv-bw 7 1.25e+06
!
interface eth1
ip address 192.168.2.1/24
mpls-te on
mpls-te link metric 10
mpls-te link max-bw 1.25e+06
mpls-te link max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06
mpls-te link rsc-clsclr 0xab
mpls-te neighbor 192.168.2.2 as 65000
link-params
enable
metric 10
max-bw 1.25e+07
max-rsv-bw 1.25e+06
unrsv-bw 0 1.25e+06
unrsv-bw 1 1.25e+06
unrsv-bw 2 1.25e+06
unrsv-bw 3 1.25e+06
unrsv-bw 4 1.25e+06
unrsv-bw 5 1.25e+06
unrsv-bw 6 1.25e+06
unrsv-bw 7 1.25e+06
neighbor 192.168.2.2 as 65000
@end group
@end example

View File

@ -22,8 +22,8 @@ BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VN
information between NVAs. BGP based IP VPN support is defined in
@cite{RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs)}, and
@cite{RFC4659, BGP-MPLS IP Virtual Private Network (VPN) Extension for
IPv6 VPN }. Both the Encapsulation Subsequent Address Family Identifier
(SAFI) and the Tunnel Encapsulation Attribute, @cite{RFC5512, The BGP
IPv6 VPN }. Encapsulation information is provided via
the Tunnel Encapsulation Attribute, @cite{RFC5512, The BGP
Encapsulation Subsequent Address Family Identifier (SAFI) and the BGP
Tunnel Encapsulation Attribute}, are supported.
@ -83,12 +83,10 @@ operating within a VN.
@node General VNC Configuration
@subsection General VNC Configuration
@deffn {VNC} {vnc advertise-un-method encap-safi|encap-attr} {}
Advertise NVE underlay-network IP addresses using the encapsulation SAFI
(@code{encap-safi}) or the UN address sub-TLV of the Tunnel Encapsulation attribute
(@code{encap-attr}). When @code{encap-safi} is used, neighbors under
@code{address-family encap} and/or @code{address-family encapv6} must be
configured. The default is @code{encap-attr}.
@deffn {VNC} {vnc advertise-un-method encap-attr} {}
Advertise NVE underlay-network IP addresses using
the UN address sub-TLV of the Tunnel Encapsulation attribute
(@code{encap-attr}). The default is @code{encap-attr}.
@end deffn
@node RFP Related Configuration
@ -356,8 +354,7 @@ by receiving NVAs.
The second form, @code{rt import} specifies an @var{import rt-list},
which is a filter for incoming routes.
In order to be made available to NVEs in the group,
incoming BGP VPN and @w{ENCAP} @w{SAFI} (when @code{vnc
advertise-un-method encap-safi} is set) routes must have
incoming BGP VPN @w{SAFI} routes must have
RT lists that have at least one route target in common with the
group's @var{import rt-list}.
@ -1010,7 +1007,7 @@ router bgp 64512
neighbor 192.168.1.101 remote-as 64512
neighbor 192.168.1.102 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate
exit-address-family
@ -1043,7 +1040,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
neighbor 192.168.1.102 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
neighbor 192.168.1.102 activate
exit-address-family
@ -1066,7 +1063,7 @@ router bgp 64512
neighbor 192.168.1.101 remote-as 64512
neighbor 192.168.1.102 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
neighbor 192.168.1.101 activate
exit-address-family
@ -1131,7 +1128,7 @@ router bgp 64512
neighbor 172.16.2.2 route-reflector-client
exit-address-family
!
address-family vpnv4 unicast
address-family ipv4 vpn
neighbor 192.168.1.102 activate
neighbor 192.168.1.103 activate
neighbor 192.168.1.104 activate
@ -1161,7 +1158,7 @@ router bgp 64512
no neighbor 192.168.1.103 activate
exit-address-family
!
address-family vpnv4 unicast
address-family ipv4 vpn
neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate
neighbor 192.168.1.103 activate
@ -1250,7 +1247,7 @@ router bgp 64512
neighbor 192.168.1.102 route-reflector-client
exit-address-family
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate
@ -1269,7 +1266,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
exit-address-family
@ -1290,7 +1287,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
exit-address-family
@ -1381,7 +1378,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
exit-address-family
@ -1402,7 +1399,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
exit-address-family
@ -1450,7 +1447,7 @@ router bgp 64512
neighbor 192.168.1.102 description iBGP-client-192-168-1-102
neighbor 192.168.1.102 route-reflector-client
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate
neighbor 192.168.1.104 activate
@ -1470,7 +1467,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
neighbor 192.168.1.104 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
neighbor 192.168.1.104 activate
exit-address-family
@ -1493,7 +1490,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512
neighbor 192.168.1.104 remote-as 64512
address-family vpnv4
address-family ipv4 vpn
neighbor 192.168.1.100 activate
neighbor 192.168.1.104 activate
exit-address-family

View File

@ -366,6 +366,7 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@ -407,6 +408,7 @@ void eigrp_zebra_route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));

View File

@ -261,6 +261,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
@ -329,6 +330,7 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;

View File

@ -1,5 +1,5 @@
/*
* Utilities and interfaces for managing POSIX threads
* Utilities and interfaces for managing POSIX threads within FRR.
* Copyright (C) 2017 Cumulus Networks
*
* This program is free software; you can redistribute it and/or modify
@ -25,78 +25,99 @@
#include "memory.h"
#include "hash.h"
DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread");
DEFINE_MTYPE(LIB, FRR_PTHREAD, "FRR POSIX Thread");
DEFINE_MTYPE(LIB, PTHREAD_PRIM, "POSIX synchronization primitives");
/* id for next created pthread */
static unsigned int next_id = 0;
/* Hash table of all frr_pthreads along with synchronization primitive(s) and
* hash table callbacks.
* ------------------------------------------------------------------------ */
static struct hash *pthread_table;
static pthread_mutex_t pthread_table_mtx = PTHREAD_MUTEX_INITIALIZER;
/* default frr_pthread start/stop routine prototypes */
static void *fpt_run(void *arg);
static int fpt_halt(struct frr_pthread *fpt, void **res);
/* pthread_table->hash_cmp */
static int pthread_table_hash_cmp(const void *value1, const void *value2)
/* default frr_pthread attributes */
struct frr_pthread_attr frr_pthread_attr_default = {
.id = 0,
.start = fpt_run,
.stop = fpt_halt,
.name = "Anonymous",
};
/* hash table to keep track of all frr_pthreads */
static struct hash *frr_pthread_hash;
static pthread_mutex_t frr_pthread_hash_mtx = PTHREAD_MUTEX_INITIALIZER;
/* frr_pthread_hash->hash_cmp */
static int frr_pthread_hash_cmp(const void *value1, const void *value2)
{
const struct frr_pthread *tq1 = value1;
const struct frr_pthread *tq2 = value2;
return (tq1->id == tq2->id);
return (tq1->attr.id == tq2->attr.id);
}
/* pthread_table->hash_key */
static unsigned int pthread_table_hash_key(void *value)
/* frr_pthread_hash->hash_key */
static unsigned int frr_pthread_hash_key(void *value)
{
return ((struct frr_pthread *)value)->id;
return ((struct frr_pthread *)value)->attr.id;
}
/* ------------------------------------------------------------------------ */
void frr_pthread_init()
{
pthread_mutex_lock(&pthread_table_mtx);
pthread_mutex_lock(&frr_pthread_hash_mtx);
{
pthread_table = hash_create(pthread_table_hash_key,
pthread_table_hash_cmp, NULL);
frr_pthread_hash = hash_create(frr_pthread_hash_key,
frr_pthread_hash_cmp, NULL);
}
pthread_mutex_unlock(&pthread_table_mtx);
pthread_mutex_unlock(&frr_pthread_hash_mtx);
}
void frr_pthread_finish()
{
pthread_mutex_lock(&pthread_table_mtx);
pthread_mutex_lock(&frr_pthread_hash_mtx);
{
hash_clean(pthread_table,
hash_clean(frr_pthread_hash,
(void (*)(void *))frr_pthread_destroy);
hash_free(pthread_table);
hash_free(frr_pthread_hash);
}
pthread_mutex_unlock(&pthread_table_mtx);
pthread_mutex_unlock(&frr_pthread_hash_mtx);
}
struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
void *(*start_routine)(void *),
int (*stop_routine)(void **,
struct frr_pthread *))
struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr)
{
static struct frr_pthread holder = {0};
struct frr_pthread *fpt = NULL;
pthread_mutex_lock(&pthread_table_mtx);
attr = attr ? attr : &frr_pthread_attr_default;
pthread_mutex_lock(&frr_pthread_hash_mtx);
{
holder.id = id;
holder.attr.id = attr->id;
if (!hash_lookup(pthread_table, &holder)) {
struct frr_pthread *fpt = XCALLOC(
MTYPE_FRR_PTHREAD, sizeof(struct frr_pthread));
fpt->id = id;
fpt->master = thread_master_create(name);
fpt->start_routine = start_routine;
fpt->stop_routine = stop_routine;
fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
if (!hash_lookup(frr_pthread_hash, &holder)) {
fpt = XCALLOC(MTYPE_FRR_PTHREAD,
sizeof(struct frr_pthread));
/* create new thread master */
fpt->master = thread_master_create(attr->name);
/* set attributes */
fpt->attr = *attr;
if (attr == &frr_pthread_attr_default)
fpt->attr.id = frr_pthread_get_id();
/* initialize startup synchronization primitives */
fpt->running_cond_mtx = XCALLOC(
MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t));
fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM,
sizeof(pthread_cond_t));
pthread_mutex_init(fpt->running_cond_mtx, NULL);
pthread_cond_init(fpt->running_cond, NULL);
hash_get(pthread_table, fpt, hash_alloc_intern);
/* insert into global thread hash */
hash_get(frr_pthread_hash, fpt, hash_alloc_intern);
}
}
pthread_mutex_unlock(&pthread_table_mtx);
pthread_mutex_unlock(&frr_pthread_hash_mtx);
return fpt;
}
@ -104,7 +125,11 @@ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
void frr_pthread_destroy(struct frr_pthread *fpt)
{
thread_master_free(fpt->master);
XFREE(MTYPE_FRR_PTHREAD, fpt->name);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond);
XFREE(MTYPE_FRR_PTHREAD, fpt);
}
@ -113,74 +138,82 @@ struct frr_pthread *frr_pthread_get(unsigned int id)
static struct frr_pthread holder = {0};
struct frr_pthread *fpt;
pthread_mutex_lock(&pthread_table_mtx);
pthread_mutex_lock(&frr_pthread_hash_mtx);
{
holder.id = id;
fpt = hash_lookup(pthread_table, &holder);
holder.attr.id = id;
fpt = hash_lookup(frr_pthread_hash, &holder);
}
pthread_mutex_unlock(&pthread_table_mtx);
pthread_mutex_unlock(&frr_pthread_hash_mtx);
return fpt;
}
int frr_pthread_run(unsigned int id, const pthread_attr_t *attr, void *arg)
int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr)
{
struct frr_pthread *fpt = frr_pthread_get(id);
int ret;
if (!fpt)
return -1;
ret = pthread_create(&fpt->thread, attr, fpt->attr.start, fpt);
ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg);
/* Per pthread_create(3), the contents of fpt->thread are undefined if
* pthread_create() did not succeed. Reset this value to zero. */
/*
* Per pthread_create(3), the contents of fpt->thread are undefined if
* pthread_create() did not succeed. Reset this value to zero.
*/
if (ret < 0)
memset(&fpt->thread, 0x00, sizeof(fpt->thread));
return ret;
}
/**
* Calls the stop routine for the frr_pthread and resets any relevant fields.
*
* @param fpt - the frr_pthread to stop
* @param result - pointer to result pointer
* @return the return code from the stop routine
*/
static int frr_pthread_stop_actual(struct frr_pthread *fpt, void **result)
void frr_pthread_wait_running(struct frr_pthread *fpt)
{
int ret = (*fpt->stop_routine)(result, fpt);
pthread_mutex_lock(fpt->running_cond_mtx);
{
while (!fpt->running)
pthread_cond_wait(fpt->running_cond,
fpt->running_cond_mtx);
}
pthread_mutex_unlock(fpt->running_cond_mtx);
}
void frr_pthread_notify_running(struct frr_pthread *fpt)
{
pthread_mutex_lock(fpt->running_cond_mtx);
{
fpt->running = true;
pthread_cond_signal(fpt->running_cond);
}
pthread_mutex_unlock(fpt->running_cond_mtx);
}
int frr_pthread_stop(struct frr_pthread *fpt, void **result)
{
int ret = (*fpt->attr.stop)(fpt, result);
memset(&fpt->thread, 0x00, sizeof(fpt->thread));
return ret;
}
int frr_pthread_stop(unsigned int id, void **result)
{
struct frr_pthread *fpt = frr_pthread_get(id);
return frr_pthread_stop_actual(fpt, result);
}
/**
/*
* Callback for hash_iterate to stop all frr_pthread's.
*/
static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg)
{
struct frr_pthread *fpt = hb->data;
frr_pthread_stop_actual(fpt, NULL);
frr_pthread_stop(fpt, NULL);
}
void frr_pthread_stop_all()
{
pthread_mutex_lock(&pthread_table_mtx);
pthread_mutex_lock(&frr_pthread_hash_mtx);
{
hash_iterate(pthread_table, frr_pthread_stop_all_iter, NULL);
hash_iterate(frr_pthread_hash, frr_pthread_stop_all_iter, NULL);
}
pthread_mutex_unlock(&pthread_table_mtx);
pthread_mutex_unlock(&frr_pthread_hash_mtx);
}
unsigned int frr_pthread_get_id()
{
/* just a sanity check, this should never happen */
assert(next_id <= INT_MAX - 1);
return next_id++;
}
@ -188,3 +221,60 @@ void frr_pthread_yield(void)
{
(void)sched_yield();
}
/*
* ----------------------------------------------------------------------------
* Default Event Loop
* ----------------------------------------------------------------------------
*/
/* dummy task for sleeper pipe */
static int fpt_dummy(struct thread *thread)
{
return 0;
}
/* poison pill task to end event loop */
static int fpt_finish(struct thread *thread)
{
struct frr_pthread *fpt = THREAD_ARG(thread);
atomic_store_explicit(&fpt->running, false, memory_order_relaxed);
return 0;
}
/* stop function, called from other threads to halt this one */
static int fpt_halt(struct frr_pthread *fpt, void **res)
{
thread_add_event(fpt->master, &fpt_finish, fpt, 0, NULL);
pthread_join(fpt->thread, res);
fpt = NULL;
return 0;
}
/* entry pthread function & main event loop */
static void *fpt_run(void *arg)
{
struct frr_pthread *fpt = arg;
fpt->master->owner = pthread_self();
int sleeper[2];
pipe(sleeper);
thread_add_read(fpt->master, &fpt_dummy, NULL, sleeper[0], NULL);
fpt->master->handle_signals = false;
frr_pthread_notify_running(fpt);
struct thread task;
while (atomic_load_explicit(&fpt->running, memory_order_relaxed)) {
if (thread_fetch(fpt->master, &task)) {
thread_call(&task);
}
}
close(sleeper[1]);
close(sleeper[0]);
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Utilities and interfaces for managing POSIX threads
* Utilities and interfaces for managing POSIX threads within FRR.
* Copyright (C) 2017 Cumulus Networks
*
* This program is free software; you can redistribute it and/or modify
@ -21,36 +21,73 @@
#define _FRR_PTHREAD_H
#include <pthread.h>
#include "frratomic.h"
#include "memory.h"
#include "thread.h"
DECLARE_MTYPE(FRR_PTHREAD);
DECLARE_MTYPE(PTHREAD_PRIM);
struct frr_pthread;
struct frr_pthread_attr;
struct frr_pthread_attr {
int id;
void *(*start)(void *);
int (*stop)(struct frr_pthread *, void **);
const char *name;
};
struct frr_pthread {
/* pthread id */
pthread_t thread;
/* frr thread identifier */
unsigned int id;
/* thread master for this pthread's thread.c event loop */
struct thread_master *master;
/* start routine */
void *(*start_routine)(void *);
/* caller-specified data; start & stop funcs, name, id */
struct frr_pthread_attr attr;
/* stop routine */
int (*stop_routine)(void **, struct frr_pthread *);
/*
* Notification mechanism for allowing pthreads to notify their parents
* when they are ready to do work. This mechanism has two associated
* functions:
*
* - frr_pthread_wait_running()
* This function should be called by the spawning thread after
* frr_pthread_run(). It safely waits until the spawned thread
* indicates that is ready to do work by posting to the condition
* variable.
*
* - frr_pthread_notify_running()
* This function should be called by the spawned thread when it is
* ready to do work. It will wake up any threads waiting on the
* previously described condition.
*/
pthread_cond_t *running_cond;
pthread_mutex_t *running_cond_mtx;
_Atomic bool running;
/* the (hopefully descriptive) name of this thread */
char *name;
/*
* Fake thread-specific storage. No constraints on usage. Helpful when
* creating reentrant pthread implementations. Can be used to pass
* argument to pthread entry function.
*/
void *data;
};
/* Initializes this module.
extern struct frr_pthread_attr frr_pthread_attr_default;
/*
* Initializes this module.
*
* Must be called before using any of the other functions.
*/
void frr_pthread_init(void);
/* Uninitializes this module.
/*
* Uninitializes this module.
*
* Destroys all registered frr_pthread's and internal data structures.
*
@ -59,34 +96,23 @@ void frr_pthread_init(void);
*/
void frr_pthread_finish(void);
/* Creates a new frr_pthread.
/*
* Creates a new frr_pthread with the given attributes.
*
* If the provided ID is already assigned to an existing frr_pthread, the
* return value will be NULL.
*
* @param name - the name of the thread. Doesn't have to be unique, but it
* probably should be. This value is copied and may be safely free'd upon
* return.
*
* @param id - the integral ID of the thread. MUST be unique. The caller may
* use this id to retrieve the thread.
*
* @param start_routine - start routine for the pthread, will be passed to
* pthread_create (see those docs for details)
*
* @param stop_routine - stop routine for the pthread, called to terminate the
* thread. This function should gracefully stop the pthread and clean up any
* thread-specific resources. The passed pointer is used to return a data
* result.
* The 'attr' argument should be filled out with the desired attributes,
* including ID, start and stop functions and the desired name. Alternatively,
* if attr is NULL, the default attributes will be used. The pthread will be
* set up to run a basic threadmaster loop and the name will be "Anonymous".
* Scheduling tasks onto the threadmaster in the 'master' field of the returned
* frr_pthread will cause them to run on that pthread.
*
* @param attr - the thread attributes
* @return the created frr_pthread upon success, or NULL upon failure
*/
struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
void *(*start_routine)(void *),
int (*stop_routine)(void **,
struct frr_pthread *));
struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr);
/* Destroys an frr_pthread.
/*
* Destroys an frr_pthread.
*
* Assumes that the associated pthread, if any, has already terminated.
*
@ -94,38 +120,66 @@ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
*/
void frr_pthread_destroy(struct frr_pthread *fpt);
/* Gets an existing frr_pthread by its id.
/*
* Gets an existing frr_pthread by its id.
*
* @return frr_thread associated with the provided id, or NULL on error
*/
struct frr_pthread *frr_pthread_get(unsigned int id);
/* Creates a new pthread and binds it to a frr_pthread.
/*
* Creates a new pthread and binds it to a frr_pthread.
*
* This function is a wrapper for pthread_create. The first parameter is the
* frr_pthread to bind the created pthread to. All subsequent arguments are
* passed unmodified to pthread_create().
* passed unmodified to pthread_create(). The frr_pthread * provided will be
* used as the argument to the pthread entry function. If it is necessary to
* pass additional data, the 'data' field in the frr_pthread may be used.
*
* This function returns the same code as pthread_create(). If the value is
* zero, the provided frr_pthread is bound to a running POSIX thread. If the
* value is less than zero, the provided frr_pthread is guaranteed to be a
* clean instance that may be susbsequently passed to frr_pthread_run().
*
* @param id - frr_pthread to bind the created pthread to
* @param fpt - frr_pthread * to run
* @param attr - see pthread_create(3)
* @param arg - see pthread_create(3)
*
* @return see pthread_create(3)
*/
int frr_pthread_run(unsigned int id, const pthread_attr_t *attr, void *arg);
int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr);
/* Stops an frr_pthread with a result.
/*
* Waits until the specified pthread has finished setting up and is ready to
* begin work.
*
* @param id - frr_pthread to stop
* If the pthread's code makes use of the startup synchronization mechanism,
* this function should be called before attempting to use the functionality
* exposed by the pthread. It waits until the 'running' condition is satisfied
* (see struct definition of frr_pthread).
*
* @param fpt - the frr_pthread * to wait on
*/
void frr_pthread_wait_running(struct frr_pthread *fpt);
/*
* Notifies other pthreads that the calling thread has finished setting up and
* is ready to begin work.
*
* This will allow any other pthreads waiting in 'frr_pthread_wait_running' to
* proceed.
*
* @param fpt - the frr_pthread * that has finished setting up
*/
void frr_pthread_notify_running(struct frr_pthread *fpt);
/*
* Stops a frr_pthread with a result.
*
* @param fpt - frr_pthread * to stop
* @param result - where to store the thread's result, if any. May be NULL if a
* result is not needed.
*/
int frr_pthread_stop(unsigned int id, void **result);
int frr_pthread_stop(struct frr_pthread *fpt, void **result);
/* Stops all frr_pthread's. */
void frr_pthread_stop_all(void);
@ -133,7 +187,8 @@ void frr_pthread_stop_all(void);
/* Yields the current thread of execution */
void frr_pthread_yield(void);
/* Returns a unique identifier for use with frr_pthread_new().
/*
* Returns a unique identifier for use with frr_pthread_new().
*
* Internally, this is an integer that increments after each call to this
* function. Because the number of pthreads created should never exceed INT_MAX

View File

@ -210,6 +210,9 @@ void if_delete(struct interface *ifp)
if_link_params_free(ifp);
if (ifp->desc)
XFREE(MTYPE_TMP, ifp->desc);
XFREE(MTYPE_IF, ifp);
}
@ -219,6 +222,18 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
struct vrf *vrf;
struct interface if_tmp;
if (vrf_id == VRF_UNKNOWN) {
struct interface *ifp;
RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) {
ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
if (ifp)
return ifp;
}
return NULL;
}
vrf = vrf_lookup_by_id(vrf_id);
if (!vrf)
return NULL;

View File

@ -452,6 +452,13 @@ struct nbr_connected {
/* Prototypes. */
extern int if_cmp_name_func(char *, char *);
/*
* Passing in VRF_UNKNOWN is a valid thing to do, unless we
* are creating a new interface.
*
* This is useful for vrf route-leaking. So more than anything
* else think before you use VRF_UNKNOWN
*/
extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
extern struct interface *if_create(const char *name, vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);

View File

@ -89,6 +89,12 @@ typedef unsigned int mpls_lse_t;
/* MPLS label value as a 32-bit (mostly we only care about the label value). */
typedef unsigned int mpls_label_t;
struct mpls_label_stack {
uint8_t num_labels;
uint8_t reserved[3];
mpls_label_t label[0]; /* 1 or more labels */
};
/* The MPLS explicit-null label is 0 which means when you memset a mpls_label_t
* to zero you have set that variable to explicit-null which was probably not
* your intent. The work-around is to use one bit to indicate if the

View File

@ -124,7 +124,7 @@ const char *nexthop_type_to_str(enum nexthop_types_t nh_type)
*/
int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2)
{
struct nexthop_label *nhl1, *nhl2;
struct mpls_label_stack *nhl1, *nhl2;
nhl1 = nh1->nh_label;
nhl2 = nh2->nh_label;
@ -210,12 +210,12 @@ void nexthops_free(struct nexthop *nexthop)
void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t type,
u_int8_t num_labels, mpls_label_t *label)
{
struct nexthop_label *nh_label;
struct mpls_label_stack *nh_label;
int i;
nexthop->nh_label_type = type;
nh_label = XCALLOC(MTYPE_NH_LABEL,
sizeof(struct nexthop_label)
sizeof(struct mpls_label_stack)
+ num_labels * sizeof(mpls_label_t));
nh_label->num_labels = num_labels;
for (i = 0; i < num_labels; i++)

View File

@ -55,13 +55,6 @@ enum blackhole_type {
((type) == NEXTHOP_TYPE_IFINDEX || (type) == NEXTHOP_TYPE_BLACKHOLE) \
? (type) : ((type) | 1)
/* Nexthop label structure. */
struct nexthop_label {
u_int8_t num_labels;
u_int8_t reserved[3];
mpls_label_t label[0]; /* 1 or more labels. */
};
/* Nexthop structure. */
struct nexthop {
struct nexthop *next;
@ -107,7 +100,7 @@ struct nexthop {
enum lsp_types_t nh_label_type;
/* Label(s) associated with this nexthop. */
struct nexthop_label *nh_label;
struct mpls_label_stack *nh_label;
};
/* The following for loop allows to iterate over the nexthop

View File

@ -25,10 +25,11 @@
#include "openbsd-tree.h"
#include "linklist.h"
typedef u_int16_t ns_id_t;
typedef u_int32_t ns_id_t;
/* The default NS ID */
/* the default NS ID */
#define NS_DEFAULT 0
#define NS_UNKNOWN UINT32_MAX
/* Default netns directory (Linux) */
#define NS_RUN_DIR "/var/run/netns"

View File

@ -919,6 +919,8 @@ struct thread *funcname_thread_add_event(struct thread_master *m,
*/
static void thread_cancel_rw(struct thread_master *master, int fd, short state)
{
bool found = false;
/* Cancel POLLHUP too just in case some bozo set it */
state |= POLLHUP;
@ -926,8 +928,18 @@ static void thread_cancel_rw(struct thread_master *master, int fd, short state)
nfds_t i;
for (i = 0; i < master->handler.pfdcount; i++)
if (master->handler.pfds[i].fd == fd)
if (master->handler.pfds[i].fd == fd) {
found = true;
break;
}
if (!found) {
zlog_debug(
"[!] Received cancellation request for nonexistent rw job");
zlog_debug("[!] threadmaster: %s | fd: %d",
master->name ? master->name : "", fd);
return;
}
/* NOT out event. */
master->handler.pfds[i].events &= ~(state);

View File

@ -94,7 +94,7 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
int new = 0;
if (debug_vrf)
zlog_debug("VRF_GET: %s(%d)", name, vrf_id);
zlog_debug("VRF_GET: %s(%u)", name, vrf_id);
/* Nothing to see, move along here */
if (!name && vrf_id == VRF_UNKNOWN)
@ -267,8 +267,8 @@ void *vrf_info_lookup(vrf_id_t vrf_id)
* VRF bit-map
*/
#define VRF_BITMAP_NUM_OF_GROUPS 8
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
#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 */
@ -355,7 +355,7 @@ static void vrf_autocomplete(vector comps, struct cmd_token *token)
struct vrf *vrf = NULL;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if (vrf->vrf_id != 0)
if (vrf->vrf_id != VRF_DEFAULT)
vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
}
}

View File

@ -32,8 +32,7 @@
/* The default VRF ID */
#define VRF_DEFAULT 0
#define VRF_UNKNOWN UINT16_MAX
#define VRF_ALL UINT16_MAX - 1
#define VRF_UNKNOWN UINT32_MAX
/* Pending: May need to refine this. */
#ifndef IFLA_VRF_MAX

View File

@ -291,7 +291,7 @@ void zclient_create_header(struct stream *s, uint16_t command, vrf_id_t vrf_id)
stream_putw(s, ZEBRA_HEADER_SIZE);
stream_putc(s, ZEBRA_HEADER_MARKER);
stream_putc(s, ZSERV_VERSION);
stream_putw(s, vrf_id);
stream_putl(s, vrf_id);
stream_putw(s, command);
}
@ -306,7 +306,7 @@ int zclient_read_header(struct stream *s, int sock, u_int16_t *size,
*size -= ZEBRA_HEADER_SIZE;
STREAM_GETC(s, *marker);
STREAM_GETC(s, *version);
STREAM_GETW(s, *vrf_id);
STREAM_GETL(s, *vrf_id);
STREAM_GETW(s, *cmd);
if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) {
@ -389,17 +389,18 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
vrf_id);
/* Flush all redistribute request. */
if (vrf_id == VRF_DEFAULT)
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (zclient->mi_redist[afi][i].enabled) {
if (vrf_id == VRF_DEFAULT) {
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!zclient->mi_redist[afi][i].enabled)
continue;
struct listnode *node;
u_short *id;
for (ALL_LIST_ELEMENTS_RO(
zclient->mi_redist[afi][i]
.instances,
node, id))
.instances, node, id))
if (!(i == zclient->redist_default
&& *id == zclient->instance))
zebra_redistribute_send(
@ -408,6 +409,8 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
*id,
VRF_DEFAULT);
}
}
}
/* Flush all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
@ -447,21 +450,22 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Set unwanted redistribute route. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
vrf_bitmap_set(zclient->redist[afi][zclient->redist_default],
vrf_bitmap_unset(zclient->redist[afi][zclient->redist_default],
vrf_id);
/* Flush all redistribute request. */
if (vrf_id == VRF_DEFAULT)
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (zclient->mi_redist[afi][i].enabled) {
if (vrf_id == VRF_DEFAULT) {
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!zclient->mi_redist[afi][i].enabled)
continue;
struct listnode *node;
u_short *id;
for (ALL_LIST_ELEMENTS_RO(
zclient->mi_redist[afi][i]
.instances,
node, id))
.instances, node, id))
if (!(i == zclient->redist_default
&& *id == zclient->instance))
zebra_redistribute_send(
@ -470,6 +474,8 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
*id,
VRF_DEFAULT);
}
}
}
/* Flush all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
@ -608,6 +614,33 @@ static int zclient_connect(struct thread *t)
return zclient_start(zclient);
}
int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
bool exact_match, vrf_id_t vrf_id)
{
struct stream *s;
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, command, vrf_id);
stream_putc(s, (exact_match) ? 1 : 0);
stream_putw(s, PREFIX_FAMILY(p));
stream_putc(s, p->prefixlen);
switch (PREFIX_FAMILY(p)) {
case AF_INET:
stream_put_in_addr(s, &p->u.prefix4);
break;
case AF_INET6:
stream_put(s, &(p->u.prefix6), 16);
break;
default:
break;
}
stream_putw_at(s, 0, stream_get_endp(s));
return zclient_send_message(zclient);
}
/*
* "xdr_encode"-like interface that allows daemon (client) to send
* a message to zebra server for a route that needs to be
@ -942,6 +975,8 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
}
stream_putw(s, api->nexthop_num);
if (api->nexthop_num)
stream_putw(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
@ -1091,6 +1126,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
return -1;
}
if (api->nexthop_num)
STREAM_GETW(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
@ -1677,7 +1715,7 @@ struct interface *zebra_interface_vrf_update_read(struct stream *s,
{
unsigned int ifindex;
struct interface *ifp;
vrf_id_t new_id = VRF_DEFAULT;
vrf_id_t new_id;
/* Get interface index. */
ifindex = stream_getl(s);
@ -2043,7 +2081,7 @@ static int zclient_read(struct thread *thread)
length = stream_getw(zclient->ibuf);
marker = stream_getc(zclient->ibuf);
version = stream_getc(zclient->ibuf);
vrf_id = stream_getw(zclient->ibuf);
vrf_id = stream_getl(zclient->ibuf);
command = stream_getw(zclient->ibuf);
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) {
@ -2346,9 +2384,9 @@ void zclient_interface_set_master(struct zclient *client,
zclient_create_header(s, ZEBRA_INTERFACE_SET_MASTER, master->vrf_id);
stream_putw(s, master->vrf_id);
stream_putl(s, master->vrf_id);
stream_putl(s, master->ifindex);
stream_putw(s, slave->vrf_id);
stream_putl(s, slave->vrf_id);
stream_putl(s, slave->ifindex);
stream_putw_at(s, 0, stream_get_endp(s));

View File

@ -40,7 +40,7 @@
#define ZEBRA_MAX_PACKET_SIZ 4096
/* Zebra header size. */
#define ZEBRA_HEADER_SIZE 8
#define ZEBRA_HEADER_SIZE 10
/* special socket path name to use TCP
* @ is used as first character because that's abstract socket names on Linux
@ -227,7 +227,7 @@ struct zserv_header {
* always set to 255 in new zserv.
*/
uint8_t version;
#define ZSERV_VERSION 4
#define ZSERV_VERSION 5
vrf_id_t vrf_id;
uint16_t command;
};
@ -281,6 +281,7 @@ struct zapi_route {
u_int32_t mtu;
vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
struct ethaddr rmac;
};
@ -420,6 +421,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t *new_vrf_id);
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
#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
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated));
@ -478,6 +484,9 @@ extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *,
struct zapi_ipv6 *)
__attribute__((deprecated));
extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *);
extern int zclient_send_rnh(struct zclient *zclient, int command,
struct prefix *p, bool exact_match,
vrf_id_t vrf_id);
extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *);
extern int zapi_route_decode(struct stream *, struct zapi_route *);
bool zapi_route_notify_decode(struct stream *s, struct prefix *p,

View File

@ -486,7 +486,7 @@ typedef u_int16_t zebra_size_t;
typedef u_int16_t zebra_command_t;
/* VRF ID type. */
typedef u_int16_t vrf_id_t;
typedef uint32_t vrf_id_t;
typedef uint32_t route_tag_t;
#define ROUTE_TAG_MAX UINT32_MAX

View File

@ -95,6 +95,8 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = *p;
switch (type) {

View File

@ -901,6 +901,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
ospf6_route_copy_nexthops(route, abr_entry);
/* (7) If the routes are identical, copy the next hops over to existing
route. ospf6's route table implementation will otherwise string both
routes, but keep the older one as the best route since the routes
@ -910,6 +911,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
if (old && (ospf6_route_cmp(route, old) == 0)) {
ospf6_route_merge_nexthops(old, route);
if (is_debug)
zlog_debug("%s: Update route: %s nh count %u",
__PRETTY_FUNCTION__,
buf, listcount(route->nh_list));
/* Update RIB/FIB */
if (table->hook_add)
(*table->hook_add)(old);
@ -918,7 +925,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
ospf6_route_delete(route);
} else {
if (is_debug)
zlog_debug("Install route: %s", buf);
zlog_debug("Install route: %s nh count %u",
buf, listcount(route->nh_list));
/* ospf6_ia_add_nw_route (table, &prefix, route); */
ospf6_route_add(route, table);
}

View File

@ -117,7 +117,9 @@ static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
static void ospf6_area_route_hook_add(struct ospf6_route *route)
{
struct ospf6_route *copy = ospf6_route_copy(route);
struct ospf6_route *copy;
copy = ospf6_route_copy(route);
ospf6_route_add(copy, ospf6->route_table);
}
@ -219,6 +221,7 @@ struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df)
oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
oa->lsdb_self = ospf6_lsdb_create(oa);
oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
oa->spf_table->scope = oa;
@ -277,6 +280,7 @@ void ospf6_area_delete(struct ospf6_area *oa)
ospf6_lsdb_delete(oa->lsdb);
ospf6_lsdb_delete(oa->lsdb_self);
ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
ospf6_spf_table_finish(oa->spf_table);
ospf6_route_table_delete(oa->spf_table);

View File

@ -55,6 +55,7 @@ struct ospf6_area {
struct ospf6_lsdb *lsdb;
struct ospf6_lsdb *lsdb_self;
struct ospf6_lsdb *temp_router_lsa_lsdb;
struct ospf6_route_table *spf_table;
struct ospf6_route_table *route_table;

View File

@ -173,11 +173,136 @@ static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
return ntohl(network_order);
}
void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
struct ospf6_route *route)
{
struct ospf6_route *old_route;
struct ospf6_path *ecmp_path, *o_path = NULL;
struct listnode *anode;
struct listnode *nnode, *rnode, *rnext;
struct ospf6_nexthop *nh, *rnh;
char buf[PREFIX2STR_BUFFER];
bool route_found = false;
for (old_route = old; old_route; old_route = old_route->next) {
if (ospf6_route_is_same(old_route, route) &&
(old_route->path.type == route->path.type) &&
(old_route->path.cost == route->path.cost) &&
(old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&old_route->prefix, buf,
sizeof(buf));
zlog_debug("%s: old route %s path cost %u [%u]",
__PRETTY_FUNCTION__, buf,
old_route->path.cost,
ospf6_route_is_same(old_route,
route));
}
route_found = true;
/* check if this path exists already in
* route->paths list, if so, replace nh_list
* from asbr_entry.
*/
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
o_path)) {
if ((o_path->origin.id == route->path.origin.id)
&& (o_path->origin.adv_router ==
route->path.origin.adv_router))
break;
}
/* If path is not found in old_route paths's list,
* add a new path to route paths list and merge
* nexthops in route->path->nh_list.
* Otherwise replace existing path's nh_list.
*/
if (o_path == NULL) {
ecmp_path = ospf6_path_dup(&route->path);
/* Add a nh_list to new ecmp path */
ospf6_copy_nexthops(ecmp_path->nh_list,
route->nh_list);
/* Merge nexthop to existing route's nh_list */
ospf6_route_merge_nexthops(old_route, route);
/* Update RIB/FIB */
if (ospf6->route_table->hook_add)
(*ospf6->route_table->hook_add)
(old_route);
/* Add the new path to route's path list */
listnode_add_sort(old_route->paths, ecmp_path);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf,
sizeof(buf));
zlog_debug("%s: route %s another path added with nh %u, Paths %u",
__PRETTY_FUNCTION__, buf,
listcount(ecmp_path->nh_list),
old_route->paths ?
listcount(old_route->paths)
: 0);
}
} else {
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
nnode, nh)) {
for (ALL_LIST_ELEMENTS(
old_route->nh_list,
rnode, rnext, rnh)) {
if (!ospf6_nexthop_is_same(rnh,
nh))
continue;
listnode_delete(
old_route->nh_list,
rnh);
ospf6_nexthop_delete(rnh);
}
}
list_delete_all_node(o_path->nh_list);
ospf6_copy_nexthops(o_path->nh_list,
route->nh_list);
/* Merge nexthop to existing route's nh_list */
ospf6_route_merge_nexthops(old_route,
route);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix,
buf, sizeof(buf));
zlog_debug("%s: existing route %s with effective nh count %u",
__PRETTY_FUNCTION__, buf,
old_route->nh_list ?
listcount(old_route->nh_list)
: 0);
}
/* Update RIB/FIB */
if (ospf6->route_table->hook_add)
(*ospf6->route_table->hook_add)
(old_route);
}
/* Delete the new route its info added to existing
* route.
*/
ospf6_route_delete(route);
break;
}
}
if (!route_found) {
/* Add new route to existing node in ospf6 route table. */
ospf6_route_add(route, ospf6->route_table);
}
}
void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
{
struct ospf6_as_external_lsa *external;
struct prefix asbr_id;
struct ospf6_route *asbr_entry, *route;
struct ospf6_route *asbr_entry, *route, *old;
struct ospf6_path *path;
char buf[PREFIX2STR_BUFFER];
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
@ -245,12 +370,34 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
ospf6_route_copy_nexthops(route, asbr_entry);
path = ospf6_path_dup(&route->path);
ospf6_copy_nexthops(path->nh_list, asbr_entry->nh_list);
listnode_add_sort(route->paths, path);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf, sizeof(buf));
zlog_debug("AS-External route add: %s", buf);
zlog_debug("%s: AS-External %u route add %s cost %u(%u) nh %u",
__PRETTY_FUNCTION__,
(route->path.type == OSPF6_PATH_TYPE_EXTERNAL1)
? 1 : 2, buf, route->path.cost,
route->path.u.cost_e2,
listcount(route->nh_list));
}
old = ospf6_route_lookup(&route->prefix, ospf6->route_table);
if (!old) {
/* Add the new route to ospf6 instance route table. */
ospf6_route_add(route, ospf6->route_table);
} else {
/* RFC 2328 16.4 (6)
* ECMP: Keep new equal preference path in current
* route's path list, update zebra with new effective
* list along with addition of ECMP path.
*/
ospf6_asbr_update_route_ecmp_path(old, route);
}
}
void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
@ -291,16 +438,126 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
nroute = ospf6_route_next(route);
if (route->type != OSPF6_DEST_TYPE_NETWORK)
continue;
/* Route has multiple ECMP paths remove,
* matching path and update effective route's nh list.
*/
if (listcount(route->paths) > 1) {
struct listnode *anode, *anext;
struct listnode *nnode, *rnode, *rnext;
struct ospf6_nexthop *nh, *rnh;
struct ospf6_path *o_path;
bool nh_updated = false;
/* Iterate all paths of route to find maching with LSA
* remove from route path list. If route->path is same,
* replace from paths list.
*/
for (ALL_LIST_ELEMENTS(route->paths, anode, anext,
o_path)) {
if (o_path->origin.type != lsa->header->type)
continue;
if (o_path->origin.id != lsa->header->id)
continue;
if (o_path->origin.adv_router !=
lsa->header->adv_router)
continue;
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&prefix, buf, sizeof(buf));
zlog_debug(
"%s: route %s path found with nh %u",
__PRETTY_FUNCTION__, buf,
listcount(o_path->nh_list));
}
/* Remove found path's nh_list from
* the route's nh_list.
*/
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
nnode, nh)) {
for (ALL_LIST_ELEMENTS(route->nh_list,
rnode, rnext, rnh)) {
if (!ospf6_nexthop_is_same(rnh,
nh))
continue;
listnode_delete(route->nh_list,
rnh);
ospf6_nexthop_delete(rnh);
}
}
/* Delete the path from route's path list */
listnode_delete(route->paths, o_path);
ospf6_path_free(o_path);
nh_updated = true;
}
if (nh_updated) {
/* Iterate all paths and merge nexthop,
* unlesss any of the nexthop similar to
* ones deleted as part of path deletion.
*/
for (ALL_LIST_ELEMENTS(route->paths, anode,
anext, o_path)) {
ospf6_merge_nexthops(route->nh_list,
o_path->nh_list);
}
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf,
sizeof(buf));
zlog_debug("%s: AS-External %u route %s update paths %u nh %u"
, __PRETTY_FUNCTION__,
(route->path.type ==
OSPF6_PATH_TYPE_EXTERNAL1)
? 1 : 2, buf,
listcount(route->paths),
listcount(route->nh_list));
}
/* Update RIB/FIB w/ effective nh_list */
if (ospf6->route_table->hook_add)
(*ospf6->route_table->hook_add)(route);
/* route's path is similar to lsa header,
* replace route's path with route's
* paths list head.
*/
if (route->path.origin.id == lsa->header->id &&
route->path.origin.adv_router ==
lsa->header->adv_router) {
struct ospf6_path *h_path;
h_path = (struct ospf6_path *)
listgetdata(listhead(route->paths));
route->path.origin.type =
h_path->origin.type;
route->path.origin.id =
h_path->origin.id;
route->path.origin.adv_router =
h_path->origin.adv_router;
}
}
continue;
} else {
if (route->path.origin.type != lsa->header->type)
continue;
if (route->path.origin.id != lsa->header->id)
continue;
if (route->path.origin.adv_router != lsa->header->adv_router)
if (route->path.origin.adv_router !=
lsa->header->adv_router)
continue;
}
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf, sizeof(buf));
zlog_debug("AS-External route remove: %s", buf);
zlog_debug("%s: AS-External %u route remove %s cost %u(%u) nh %u",
__PRETTY_FUNCTION__,
route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
? 1 : 2, buf, route->path.cost,
route->path.u.cost_e2,
listcount(route->nh_list));
}
ospf6_route_remove(route, ospf6->route_table);
}

View File

@ -93,5 +93,7 @@ extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *);
extern int config_write_ospf6_debug_asbr(struct vty *vty);
extern void install_element_ospf6_debug_asbr(void);
extern void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
struct ospf6_route *route);
#endif /* OSPF6_ASBR_H */

View File

@ -1008,6 +1008,103 @@ DEFUN (show_ipv6_ospf6_interface,
return CMD_SUCCESS;
}
static int ospf6_interface_show_traffic(struct vty *vty,
uint32_t vrf_id,
struct interface *intf_ifp,
int display_once)
{
struct interface *ifp;
struct vrf *vrf = NULL;
struct ospf6_interface *oi = NULL;
vrf = vrf_lookup_by_id(vrf_id);
if (!display_once) {
vty_out(vty, "\n");
vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n",
"Interface", " HELLO", " DB-Desc", " LS-Req",
" LS-Update", " LS-Ack");
vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
vty_out(vty,
"--------------------------------------------------------------------------------------------\n");
}
if (intf_ifp == NULL) {
FOR_ALL_INTERFACES (vrf, ifp) {
if (ifp->info)
oi = (struct ospf6_interface *)ifp->info;
else
continue;
vty_out(vty,
"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
oi->interface->name, oi->hello_in,
oi->hello_out,
oi->db_desc_in, oi->db_desc_out,
oi->ls_req_in, oi->ls_req_out,
oi->ls_upd_in, oi->ls_upd_out,
oi->ls_ack_in, oi->ls_ack_out);
}
} else {
oi = intf_ifp->info;
if (oi == NULL)
return CMD_WARNING;
vty_out(vty,
"%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
oi->interface->name, oi->hello_in,
oi->hello_out,
oi->db_desc_in, oi->db_desc_out,
oi->ls_req_in, oi->ls_req_out,
oi->ls_upd_in, oi->ls_upd_out,
oi->ls_ack_in, oi->ls_ack_out);
}
return CMD_SUCCESS;
}
/* show interface */
DEFUN (show_ipv6_ospf6_interface_traffic,
show_ipv6_ospf6_interface_traffic_cmd,
"show ipv6 ospf6 interface traffic [IFNAME]",
SHOW_STR
IP6_STR
OSPF6_STR
INTERFACE_STR
"Protocol Packet counters\n"
IFNAME_STR)
{
int idx_ifname = 0;
int display_once = 0;
char *intf_name = NULL;
struct interface *ifp = NULL;
if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
intf_name = argv[idx_ifname]->arg;
ifp = if_lookup_by_name(intf_name, VRF_DEFAULT);
if (ifp == NULL) {
vty_out(vty,
"No such Interface: %s\n",
intf_name);
return CMD_WARNING;
}
if (ifp->info == NULL) {
vty_out(vty,
" OSPF not enabled on this interface %s\n",
intf_name);
return 0;
}
}
ospf6_interface_show_traffic(vty, VRF_DEFAULT, ifp,
display_once);
return CMD_SUCCESS;
}
DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
show_ipv6_ospf6_interface_ifname_prefix_cmd,
"show ipv6 ospf6 interface IFNAME prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]",
@ -1841,6 +1938,8 @@ void ospf6_interface_init(void)
install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
install_element(VIEW_NODE,
&show_ipv6_ospf6_interface_ifname_prefix_cmd);
install_element(VIEW_NODE,
&show_ipv6_ospf6_interface_traffic_cmd);
install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);

View File

@ -117,6 +117,19 @@ struct ospf6_interface {
/* BFD information */
void *bfd_info;
/* Statistics Fields */
u_int32_t hello_in;
u_int32_t hello_out;
u_int32_t db_desc_in;
u_int32_t db_desc_out;
u_int32_t ls_req_in;
u_int32_t ls_req_out;
u_int32_t ls_upd_in;
u_int32_t ls_upd_out;
u_int32_t ls_ack_in;
u_int32_t ls_ack_out;
u_int32_t discarded;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(ospf6_interface)

View File

@ -1404,7 +1404,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf, sizeof(buf));
zlog_debug(" route %s add", buf);
zlog_debug(" route %s add with nh count %u", buf,
listcount(route->nh_list));
}
ospf6_route_add(route, oa->route_table);

View File

@ -191,7 +191,7 @@ int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
/* ospf6 age functions */
/* calculate birth */
static void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
{
struct timeval now;

View File

@ -252,5 +252,6 @@ extern void ospf6_lsa_terminate(void);
extern int config_write_ospf6_debug_lsa(struct vty *vty);
extern void install_element_ospf6_debug_lsa(void);
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
#endif /* OSPF6_LSA_H */

View File

@ -41,4 +41,5 @@ DEFINE_MTYPE(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex")
DEFINE_MTYPE(OSPF6D, OSPF6_SPFTREE, "OSPF6 SPF tree")
DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop")
DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO, "OSPF6 ext. info")
DEFINE_MTYPE(OSPF6D, OSPF6_PATH, "OSPF6 Path")
DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other")

View File

@ -40,6 +40,7 @@ DECLARE_MTYPE(OSPF6_VERTEX)
DECLARE_MTYPE(OSPF6_SPFTREE)
DECLARE_MTYPE(OSPF6_NEXTHOP)
DECLARE_MTYPE(OSPF6_EXTERNAL_INFO)
DECLARE_MTYPE(OSPF6_PATH)
DECLARE_MTYPE(OSPF6_OTHER)
#endif /* _QUAGGA_OSPF6_MEMORY_H */

View File

@ -321,6 +321,8 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
backupseen++;
}
oi->hello_in++;
/* Execute neighbor events */
thread_execute(master, hello_received, on, 0);
if (twoway)
@ -776,6 +778,8 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
dbdesc->reserved2 = 0;
}
oi->db_desc_in++;
if (ntohl(oh->router_id) < ntohl(ospf6->router_id))
ospf6_dbdesc_recv_master(oh, on);
else if (ntohl(ospf6->router_id) < ntohl(oh->router_id))
@ -811,6 +815,8 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
return;
}
oi->ls_req_in++;
/* Process each request */
for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
@ -1370,6 +1376,8 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
+ sizeof(struct ospf6_header));
oi->ls_upd_in++;
/* Process LSAs */
for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
p < OSPF6_MESSAGE_END(oh)
@ -1407,6 +1415,8 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
return;
}
oi->ls_ack_in++;
for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
p += sizeof(struct ospf6_lsa_header)) {
@ -1777,6 +1787,8 @@ int ospf6_hello_send(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_HELLO;
oh->length = htons(p - sendbuf);
oi->hello_out++;
ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
return 0;
}
@ -1852,6 +1864,8 @@ int ospf6_dbdesc_send(struct thread *thread)
else
dst = &on->linklocal_addr;
on->ospf6_if->db_desc_out++;
ospf6_send(on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
return 0;
@ -1955,6 +1969,8 @@ int ospf6_lsreq_send(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
oh->length = htons(p - sendbuf);
on->ospf6_if->ls_req_out++;
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6,
on->ospf6_if, oh);
@ -1979,6 +1995,8 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
{
if (on) {
on->ospf6_if->ls_upd_out++;
if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
(on->ospf6_if->state == OSPF6_INTERFACE_BDR)) {
@ -1989,6 +2007,9 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
&on->linklocal_addr, on->ospf6_if, oh);
}
} else if (oi) {
oi->ls_upd_out++;
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(oi->state == OSPF6_INTERFACE_DR) ||
(oi->state == OSPF6_INTERFACE_BDR)) {
@ -2185,8 +2206,11 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
lsupdate->lsa_number = htonl(lsa_cnt);
ospf6_send_lsupdate(NULL, oi, oh);
if (IS_OSPF6_DEBUG_MESSAGE(
OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
zlog_debug("%s: LSUpdate length %d",
__PRETTY_FUNCTION__, ntohs(oh->length));
__PRETTY_FUNCTION__,
ntohs(oh->length));
memset(sendbuf, 0, iobuflen);
oh = (struct ospf6_header *)sendbuf;
@ -2263,6 +2287,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons(p - sendbuf);
on->ospf6_if->ls_ack_out++;
ospf6_send(on->ospf6_if->linklocal_addr,
&on->linklocal_addr,
on->ospf6_if, oh);
@ -2288,6 +2314,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons(p - sendbuf);
on->ospf6_if->ls_ack_out++;
ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh);
}

View File

@ -215,7 +215,7 @@ void ospf6_copy_nexthops(struct list *dst, struct list *src)
if (ospf6_nexthop_is_set(nh)) {
nh_new = ospf6_nexthop_create();
ospf6_nexthop_copy(nh_new, nh);
listnode_add(dst, nh_new);
listnode_add_sort(dst, nh_new);
}
}
}
@ -231,7 +231,7 @@ void ospf6_merge_nexthops(struct list *dst, struct list *src)
if (!ospf6_route_find_nexthop(dst, nh)) {
nh_new = ospf6_nexthop_create();
ospf6_nexthop_copy(nh_new, nh);
listnode_add(dst, nh_new);
listnode_add_sort(dst, nh_new);
}
}
}
@ -338,7 +338,7 @@ int ospf6_route_get_first_nh_index(struct ospf6_route *route)
return (-1);
}
static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
{
if (a->ifindex < b->ifindex)
return -1;
@ -351,6 +351,36 @@ static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
return 0;
}
static int ospf6_path_cmp(struct ospf6_path *a, struct ospf6_path *b)
{
if (a->origin.adv_router < b->origin.adv_router)
return -1;
else if (a->origin.adv_router > b->origin.adv_router)
return 1;
else
return 0;
}
void ospf6_path_free(struct ospf6_path *op)
{
if (op->nh_list)
list_delete_and_null(&op->nh_list);
XFREE(MTYPE_OSPF6_PATH, op);
}
struct ospf6_path *ospf6_path_dup(struct ospf6_path *path)
{
struct ospf6_path *new;
new = XCALLOC(MTYPE_OSPF6_PATH, sizeof(struct ospf6_path));
memcpy(new, path, sizeof(struct ospf6_path));
new->nh_list = list_new();
new->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
new->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
return new;
}
struct ospf6_route *ospf6_route_create(void)
{
struct ospf6_route *route;
@ -358,6 +388,9 @@ struct ospf6_route *ospf6_route_create(void)
route->nh_list = list_new();
route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
route->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
route->paths = list_new();
route->paths->cmp = (int (*)(void *, void *))ospf6_path_cmp;
route->paths->del = (void (*)(void *))ospf6_path_free;
return route;
}
@ -366,6 +399,8 @@ void ospf6_route_delete(struct ospf6_route *route)
if (route) {
if (route->nh_list)
list_delete_and_null(&route->nh_list);
if (route->paths)
list_delete_and_null(&route->paths);
XFREE(MTYPE_OSPF6_ROUTE, route);
}
}
@ -464,7 +499,13 @@ ospf6_route_lookup_identical(struct ospf6_route *route,
for (target = ospf6_route_lookup(&route->prefix, table); target;
target = target->next) {
if (ospf6_route_is_identical(target, route))
if (target->type == route->type &&
(memcmp(&target->prefix, &route->prefix,
sizeof(struct prefix)) == 0) &&
target->path.type == route->path.type &&
target->path.cost == route->path.cost &&
target->path.u.cost_e2 == route->path.u.cost_e2 &&
ospf6_route_cmp_nexthops(target, route) == 0)
return target;
}
return NULL;
@ -1083,6 +1124,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
route->path.u.cost_e2);
vty_out(vty, "Paths count: %u\n", route->paths->count);
vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
/* Nexthops */
vty_out(vty, "Nexthop:\n");

View File

@ -96,6 +96,9 @@ struct ospf6_path {
u_int32_t cost_config;
} u;
u_int32_t tag;
/* nh list for this path */
struct list *nh_list;
};
#define OSPF6_PATH_TYPE_NONE 0
@ -149,6 +152,9 @@ struct ospf6_route {
/* path */
struct ospf6_path path;
/* List of Paths. */
struct list *paths;
/* nexthop */
struct list *nh_list;
};
@ -256,6 +262,7 @@ extern void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf,
int size);
extern struct ospf6_nexthop *ospf6_nexthop_create(void);
extern int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b);
extern void ospf6_nexthop_delete(struct ospf6_nexthop *nh);
extern void ospf6_clear_nexthops(struct list *nh_list);
extern int ospf6_num_nexthops(struct list *nh_list);
@ -331,5 +338,7 @@ extern int config_write_ospf6_debug_route(struct vty *vty);
extern void install_element_ospf6_debug_route(void);
extern void ospf6_route_init(void);
extern void ospf6_clean(void);
extern void ospf6_path_free(struct ospf6_path *op);
extern struct ospf6_path *ospf6_path_dup(struct ospf6_path *path);
#endif /* OSPF6_ROUTE_H */

View File

@ -145,6 +145,7 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
v->nh_list = list_new();
v->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
v->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
v->parent = NULL;
@ -162,21 +163,20 @@ static void ospf6_vertex_delete(struct ospf6_vertex *v)
}
static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
struct ospf6_vertex *v,
uint32_t link_id)
struct ospf6_vertex *v)
{
struct ospf6_lsa *lsa;
struct ospf6_lsa *lsa = NULL;
u_int16_t type = 0;
u_int32_t id = 0, adv_router = 0;
if (VERTEX_IS_TYPE(NETWORK, v)) {
type = htons(OSPF6_LSTYPE_ROUTER);
id = link_id;
id = htonl(0);
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else {
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
type = htons(OSPF6_LSTYPE_ROUTER);
id = link_id;
id = htonl(0);
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
type = htons(OSPF6_LSTYPE_NETWORK);
@ -185,19 +185,22 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
}
}
if (type == htons(OSPF6_LSTYPE_NETWORK))
lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb);
else
lsa = ospf6_create_single_router_lsa(v->area, v->area->lsdb,
adv_router);
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
char ibuf[16], abuf[16];
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
if (lsa)
zlog_debug(" Link to: %s , V %s id %u", lsa->name,
v->name, link_id);
zlog_debug(" Link to: %s len %u, V %s", lsa->name,
ntohs(lsa->header->length), v->name);
else
zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s id %u",
zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s",
ospf6_lstype_name(type), ibuf, abuf,
v->name, link_id);
v->name);
}
return lsa;
@ -460,17 +463,14 @@ void ospf6_spf_calculation(u_int32_t router_id,
struct ospf6_vertex *root, *v, *w;
int size;
caddr_t lsdesc;
struct ospf6_lsa *lsa, *self_rtr_lsa = NULL, *rtr_lsa = NULL;
const struct route_node *end = NULL;
struct ospf6_lsa *lsa;
struct in6_addr address;
struct ospf6_lsdb *lsdb = NULL;
ospf6_spf_table_finish(result_table);
/* Install the calculating router itself as the root of the SPF tree */
/* construct root vertex */
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), router_id,
oa->lsdb_self);
lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
if (lsa == NULL) {
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: No router LSA for area %s\n", __func__,
@ -478,8 +478,6 @@ void ospf6_spf_calculation(u_int32_t router_id,
return;
}
self_rtr_lsa = lsa;
/* initialize */
candidate_list = pqueue_create();
candidate_list->cmp = ospf6_vertex_cmp;
@ -509,84 +507,6 @@ void ospf6_spf_calculation(u_int32_t router_id,
&& ospf6_router_is_stub_router(v->lsa)))
continue;
if (VERTEX_IS_TYPE(ROUTER, v)) {
/* First fetch root Router LSAs from lsdb_self */
if (v->lsa == self_rtr_lsa)
lsdb = oa->lsdb_self;
else
lsdb = v->area->lsdb;
/* Iterating multiple ROUTER LSAs from same adv router
* with different Link State ID */
end = ospf6_lsdb_head(lsdb, 2,
htons(OSPF6_LSTYPE_ROUTER),
v->lsa->header->adv_router,
&rtr_lsa);
while (rtr_lsa) {
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: Next LSA %s to process"
,__PRETTY_FUNCTION__,
rtr_lsa->name);
size = sizeof(struct ospf6_router_lsdesc);
/* For each LS description in the just-added vertex V's LSA */
for (lsdesc = OSPF6_LSA_HEADER_END(
rtr_lsa->header) + 4;
lsdesc + size <= OSPF6_LSA_END(
rtr_lsa->header);
lsdesc += size) {
lsa = ospf6_lsdesc_lsa(lsdesc, v,
rtr_lsa->header->id);
if (lsa == NULL)
continue;
if (OSPF6_LSA_IS_MAXAGE(lsa))
continue;
if (!ospf6_lsdesc_backlink(lsa,
lsdesc, v))
continue;
w = ospf6_vertex_create(lsa);
w->area = oa;
w->parent = v;
w->link_id = rtr_lsa->header->id;
if (VERTEX_IS_TYPE(ROUTER, v)) {
w->cost = v->cost
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
w->hops =
v->hops
+ (VERTEX_IS_TYPE(NETWORK, w)
? 0 : 1);
} else /* NETWORK */ {
w->cost = v->cost;
w->hops = v->hops + 1;
}
/* nexthop calculation */
if (w->hops == 0)
ospf6_add_nexthop(w->nh_list,
ROUTER_LSDESC_GET_IFID(lsdesc)
, NULL);
else if (w->hops == 1 && v->hops == 0)
ospf6_nexthop_calc(w, v, lsdesc);
else {
ospf6_copy_nexthops(w->nh_list,
v->nh_list);
}
/* add new candidate to the candidate_list */
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug(
" New candidate: %s hops %d cost %d",
w->name, w->hops,
w->cost);
pqueue_enqueue(w, candidate_list);
}
/* Fetch next Link state ID Router LSA */
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
}
} else {
/* For each LS description in the just-added vertex V's LSA */
size = (VERTEX_IS_TYPE(ROUTER, v)
? sizeof(struct ospf6_router_lsdesc)
@ -594,7 +514,7 @@ void ospf6_spf_calculation(u_int32_t router_id,
for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
lsdesc += size) {
lsa = ospf6_lsdesc_lsa(lsdesc, v, v->link_id);
lsa = ospf6_lsdesc_lsa(lsdesc, v);
if (lsa == NULL)
continue;
@ -612,23 +532,23 @@ void ospf6_spf_calculation(u_int32_t router_id,
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
w->hops =
v->hops
+ (VERTEX_IS_TYPE(NETWORK, w) ?
0 : 1);
} else /* NETWORK */ {
+ (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
} else {
/* NETWORK */
w->cost = v->cost;
w->hops = v->hops + 1;
}
/* nexthop calculation */
if (w->hops == 0)
ospf6_add_nexthop(w->nh_list,
ospf6_add_nexthop(
w->nh_list,
ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
else if (w->hops == 1 && v->hops == 0)
ospf6_nexthop_calc(w, v, lsdesc);
else {
ospf6_copy_nexthops(w->nh_list,
v->nh_list);
}
else
ospf6_copy_nexthops(w->nh_list, v->nh_list);
/* add new candidate to the candidate_list */
if (IS_OSPF6_DEBUG_SPF(PROCESS))
@ -638,10 +558,12 @@ void ospf6_spf_calculation(u_int32_t router_id,
pqueue_enqueue(w, candidate_list);
}
}
}
pqueue_delete(candidate_list);
ospf6_remove_temp_router_lsa(oa);
oa->spf_calculation++;
}
@ -1028,3 +950,153 @@ void ospf6_spf_init(void)
install_element(OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
install_element(OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
}
/* Create Aggregated Large Router-LSA from multiple Link-State IDs
* RFC 5340 A 4.3:
* When more than one router-LSA is received from a single router,
* the links are processed as if concatenated into a single LSA.*/
struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
struct ospf6_lsdb *lsdb,
uint32_t adv_router)
{
struct ospf6_lsa *lsa = NULL;
struct ospf6_lsa *rtr_lsa = NULL;
struct ospf6_lsa_header *lsa_header = NULL;
uint8_t *new_header = NULL;
const struct route_node *end = NULL;
uint16_t lsa_length, total_lsa_length = 0, num_lsa = 0;
u_int16_t type = 0;
char ifbuf[16];
uint32_t interface_id;
caddr_t lsd;
lsa_length = sizeof(struct ospf6_lsa_header) +
sizeof(struct ospf6_router_lsa);
total_lsa_length = lsa_length;
type = htons(OSPF6_LSTYPE_ROUTER);
/* First check Aggregated LSA formed earlier in Cache */
lsa = ospf6_lsdb_lookup(type, htonl(0), adv_router,
area->temp_router_lsa_lsdb);
if (lsa)
return lsa;
inet_ntop(AF_INET, &adv_router, ifbuf, sizeof(ifbuf));
/* Determine total LSA length from all link state ids */
end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
while (rtr_lsa) {
lsa = rtr_lsa;
if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
continue;
}
lsa_header = (struct ospf6_lsa_header *) rtr_lsa->header;
total_lsa_length += (ntohs(lsa_header->length)
- lsa_length);
num_lsa++;
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
}
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: adv_router %s num_lsa %u to convert.",
__PRETTY_FUNCTION__, ifbuf, num_lsa);
if (num_lsa == 1)
return lsa;
if (num_lsa == 0) {
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: adv_router %s not found in LSDB.",
__PRETTY_FUNCTION__, ifbuf);
return NULL;
}
/* Allocate memory for this LSA */
new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, total_lsa_length);
if (!new_header)
return NULL;
/* LSA information structure */
lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
sizeof(struct ospf6_lsa));
if (!lsa) {
free(new_header);
return NULL;
}
lsa->header = (struct ospf6_lsa_header *)new_header;
lsa->lsdb = area->temp_router_lsa_lsdb;
/* Fill Larger LSA Payload */
end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
if (rtr_lsa) {
if (!OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
/* Append first Link State ID LSA */
lsa_header = (struct ospf6_lsa_header *)rtr_lsa->header;
memcpy(new_header, lsa_header,
ntohs(lsa_header->length));
/* Assign new lsa length as aggregated length. */
((struct ospf6_lsa_header *)new_header)->length =
htons(total_lsa_length);
new_header += ntohs(lsa_header->length);
num_lsa--;
}
}
/* Print LSA Name */
ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
while (rtr_lsa) {
if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
continue;
}
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
lsd = OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4;
interface_id = ROUTER_LSDESC_GET_IFID(lsd);
inet_ntop(AF_INET, &interface_id, ifbuf, sizeof(ifbuf));
zlog_debug("%s: Next Router LSA %s to aggreat with len %u interface_id %s",
__PRETTY_FUNCTION__, rtr_lsa->name,
ntohs(lsa_header->length), ifbuf);
}
/* Append Next Link State ID LSA */
lsa_header = (struct ospf6_lsa_header *) rtr_lsa->header;
memcpy(new_header, (OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4),
(ntohs(lsa_header->length) - lsa_length));
new_header += (ntohs(lsa_header->length) - lsa_length);
num_lsa--;
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
}
/* Calculate birth of this lsa */
ospf6_lsa_age_set(lsa);
/* Store Aggregated LSA into area temp lsdb */
ospf6_lsdb_add(lsa, area->temp_router_lsa_lsdb);
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: LSA %s id %u type 0%x len %u num_lsa %u",
__PRETTY_FUNCTION__, lsa->name,
ntohl(lsa->header->id), ntohs(lsa->header->type),
ntohs(lsa->header->length), num_lsa);
return lsa;
}
void ospf6_remove_temp_router_lsa(struct ospf6_area *area)
{
struct ospf6_lsa *lsa = NULL;
for (ALL_LSDB(area->temp_router_lsa_lsdb, lsa)) {
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s Remove LSA %s lsa->lock %u lsdb count %u",
__PRETTY_FUNCTION__,
lsa->name, lsa->lock,
area->temp_router_lsa_lsdb->count);
ospf6_lsdb_remove(lsa, area->temp_router_lsa_lsdb);
}
}

View File

@ -149,5 +149,9 @@ extern int config_write_ospf6_debug_spf(struct vty *vty);
extern void install_element_ospf6_debug_spf(void);
extern void ospf6_spf_init(void);
extern void ospf6_spf_reason_string(unsigned int reason, char *buf, int size);
extern struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
struct ospf6_lsdb *lsdb,
uint32_t adv_router);
extern void ospf6_remove_temp_router_lsa(struct ospf6_area *area);
#endif /* OSPF6_SPF_H */

View File

@ -95,6 +95,13 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route)
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
{
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&route->prefix, buf, sizeof(buf));
zlog_debug("%s: brouter %s add with nh count %u",
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
}
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
ospf6_asbr_lsentry_add(route);
ospf6_abr_originate_summary(route);
@ -102,6 +109,13 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
{
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
char buf[PREFIX2STR_BUFFER];
prefix2str(&route->prefix, buf, sizeof(buf));
zlog_debug("%s: brouter %s del with nh count %u",
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
}
route->flag |= OSPF6_ROUTE_REMOVE;
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
ospf6_asbr_lsentry_remove(route);

View File

@ -337,6 +337,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@ -387,6 +388,7 @@ void ospf6_zebra_add_discard(struct ospf6_route *request)
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@ -420,6 +422,7 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request)
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;

View File

@ -360,6 +360,49 @@ DEFUN (show_ipv6_ospf6_database_router,
return CMD_SUCCESS;
}
DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router,
show_ipv6_ospf6_database_aggr_router_cmd,
"show ipv6 ospf6 database aggr adv-router A.B.C.D",
SHOW_STR
IPV6_STR
OSPF6_STR
"Display Link state database\n"
"Aggregated Router LSA\n"
"Search by Advertising Router\n"
"Specify Advertising Router as IPv4 address notation\n")
{
int level = OSPF6_LSDB_SHOW_LEVEL_DETAIL;
uint16_t type = htons(OSPF6_LSTYPE_ROUTER);
int idx_ipv4 = 6;
struct listnode *i;
struct ospf6 *o = ospf6;
struct ospf6_area *oa;
struct ospf6_lsdb *lsdb;
uint32_t adv_router = 0;
inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
if (adv_router == o->router_id)
lsdb = oa->lsdb_self;
else
lsdb = oa->lsdb;
if (ospf6_create_single_router_lsa(oa, lsdb,
adv_router) == NULL) {
vty_out(vty, "Adv router is not found in LSDB.");
return CMD_SUCCESS;
}
ospf6_lsdb_show(vty, level, &type, NULL, NULL,
oa->temp_router_lsa_lsdb);
/* Remove the temp cache */
ospf6_remove_temp_router_lsa(oa);
}
vty_out(vty, "\n");
return CMD_SUCCESS;
}
DEFUN (show_ipv6_ospf6_database_type_id,
show_ipv6_ospf6_database_type_id_cmd,
"show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>]",
@ -1219,6 +1262,7 @@ void ospf6_init(void)
install_element(
VIEW_NODE,
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
install_element(VIEW_NODE, &show_ipv6_ospf6_database_aggr_router_cmd);
/* Make ospf protocol socket. */
ospf6_serv_sock();

View File

@ -327,8 +327,7 @@ static int ospf_abr_nssa_am_elected(struct ospf_area *area)
struct router_lsa *rlsa;
struct in_addr *best = NULL;
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
{
LSDB_LOOP (ROUTER_LSDB(area), rn, lsa) {
/* sanity checks */
if (!lsa || (lsa->data->type != OSPF_ROUTER_LSA)
|| IS_LSA_SELF(lsa))

View File

@ -1313,22 +1313,28 @@ int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
/* Check msg type. */
if (mask & Power2[OSPF_ROUTER_LSA])
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
if (mask & Power2[OSPF_NETWORK_LSA])
LSDB_LOOP(NETWORK_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
if (mask & Power2[OSPF_SUMMARY_LSA])
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(
lsa, (void *)&param, seqnum);
}
}
@ -1336,14 +1342,16 @@ int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
if (ospf->lsdb) {
if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(lsa, (void *)&param,
seqnum);
}
/* For AS-external opaque LSAs */
if (ospf->lsdb) {
if (mask & Power2[OSPF_OPAQUE_AS_LSA])
LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa)
apiserver_sync_callback(lsa, (void *)&param, seqnum);
apiserver_sync_callback(lsa, (void *)&param,
seqnum);
}
/* Send a reply back to client with return code */
@ -1945,16 +1953,19 @@ void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv,
case OSPF_OPAQUE_LINK_LSA:
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
apiserver_flush_opaque_type_callback(lsa, (void *)&param, 0);
apiserver_flush_opaque_type_callback(
lsa, (void *)&param, 0);
break;
case OSPF_OPAQUE_AREA_LSA:
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
apiserver_flush_opaque_type_callback(lsa, (void *)&param, 0);
apiserver_flush_opaque_type_callback(
lsa, (void *)&param, 0);
break;
case OSPF_OPAQUE_AS_LSA:
LSDB_LOOP(OPAQUE_LINK_LSDB(ospf), rn, lsa)
apiserver_flush_opaque_type_callback(lsa, (void *)&param, 0);
apiserver_flush_opaque_type_callback(lsa,
(void *)&param, 0);
break;
default:
break;

View File

@ -661,7 +661,8 @@ static int ospf_ase_calculate_timer(struct thread *t)
if (area->external_routing == OSPF_AREA_NSSA)
LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
ospf_ase_calculate_route(ospf, lsa);
ospf_ase_calculate_route(ospf,
lsa);
}
/* kevinm: And add the NSSA routes in ospf_top */
LSDB_LOOP(NSSA_LSDB(ospf), rn, lsa)

View File

@ -51,6 +51,28 @@ DEFINE_QOBJ_TYPE(ospf_interface)
DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd))
DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd))
int ospf_interface_neighbor_count(struct ospf_interface *oi)
{
int count = 0;
struct route_node *rn;
struct ospf_neighbor *nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (nbr) {
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
count++;
}
}
return count;
}
int ospf_if_get_output_cost(struct ospf_interface *oi)
{
/* If all else fails, use default OSPF cost */

View File

@ -314,8 +314,8 @@ extern struct crypt_key *ospf_crypt_key_lookup(struct list *, u_char);
extern struct crypt_key *ospf_crypt_key_new(void);
extern void ospf_crypt_key_add(struct list *, struct crypt_key *);
extern int ospf_crypt_key_delete(struct list *, u_char);
extern u_char ospf_default_iftype(struct interface *ifp);
extern int ospf_interface_neighbor_count(struct ospf_interface *oi);
/* Set all multicast memberships appropriately based on the type and
state of the interface. */

View File

@ -1872,8 +1872,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
if (area->external_routing != OSPF_AREA_NSSA && !type7)
continue;
LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
{
LSDB_LOOP (NSSA_LSDB(area), rn, lsa) {
if (lsa->data->id.s_addr
== type5->data->id.s_addr) {
type7 = lsa;

View File

@ -607,30 +607,6 @@ static void free_opaque_info_per_type(void *val)
ospf_opaque_lsa_flush_schedule(lsa);
}
/* Remove "oipt" from its owner's self-originated LSA list. */
switch (oipt->lsa_type) {
case OSPF_OPAQUE_LINK_LSA: {
struct ospf_interface *oi =
(struct ospf_interface *)(oipt->owner);
listnode_delete(oi->opaque_lsa_self, oipt);
break;
}
case OSPF_OPAQUE_AREA_LSA: {
struct ospf_area *area = (struct ospf_area *)(oipt->owner);
listnode_delete(area->opaque_lsa_self, oipt);
break;
}
case OSPF_OPAQUE_AS_LSA: {
struct ospf *top = (struct ospf *)(oipt->owner);
listnode_delete(top->opaque_lsa_self, oipt);
break;
}
default:
zlog_warn("free_opaque_info_per_type: Unexpected LSA-type(%u)",
oipt->lsa_type);
break; /* This case may not exist. */
}
OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
list_delete_and_null(&oipt->id_list);
XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);

View File

@ -218,7 +218,7 @@ DEFUN_NOSH (router_ospf,
if (ospf->vrf_id != VRF_UNKNOWN)
ospf->oi_running = 1;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("Config command 'router ospf %d' received, vrf %s id %d oi_running %u",
zlog_debug("Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
instance, ospf->name ? ospf->name : "NIL",
ospf->vrf_id, ospf->oi_running);
VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
@ -3693,14 +3693,15 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
{
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
json_object *json_vrf = NULL;
json_object *json_interface_sub = NULL;
json_object *json_vrf = NULL, *json_intf_array = NULL;
json_object *json_interface_sub = NULL, *json_interface = NULL;
if (use_json) {
if (use_vrf)
json_vrf = json_object_new_object();
else
json_vrf = json;
json_intf_array = json_object_new_array();
}
if (ospf->instance) {
@ -3714,23 +3715,31 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (intf_name == NULL) {
if (use_json)
json_object_object_add(json_vrf, "interfaces",
json_intf_array);
/* Show All Interfaces.*/
FOR_ALL_INTERFACES (vrf, ifp) {
if (ospf_oi_count(ifp)) {
if (use_json)
if (use_json) {
json_interface =
json_object_new_object();
json_interface_sub =
json_object_new_object();
}
show_ip_ospf_interface_sub(vty, ospf, ifp,
json_interface_sub,
use_json);
if (use_json)
if (use_json) {
json_object_array_add(json_intf_array,
json_interface);
json_object_object_add(
json_vrf, ifp->name,
json_interface, ifp->name,
json_interface_sub);
}
}
}
} else {
/* Interface name is specified. */
ifp = if_lookup_by_name(intf_name, ospf->vrf_id);
@ -3741,17 +3750,25 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
else
vty_out(vty, "No such interface name\n");
} else {
if (use_json)
if (use_json) {
json_interface_sub = json_object_new_object();
json_interface = json_object_new_object();
json_object_object_add(json_vrf, "interfaces",
json_intf_array);
}
show_ip_ospf_interface_sub(
vty, ospf, ifp, json_interface_sub, use_json);
if (use_json)
json_object_object_add(json_vrf, ifp->name,
if (use_json) {
json_object_array_add(json_intf_array,
json_interface);
json_object_object_add(json_interface,
ifp->name,
json_interface_sub);
}
}
}
if (use_json) {
if (use_vrf) {
@ -4283,13 +4300,15 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf,
{
struct ospf_interface *oi;
struct listnode *node;
json_object *json_vrf = NULL;
json_object *json_vrf = NULL, *json_nbr_array = NULL;
json_object *json_nbr_sub = NULL;
if (use_json) {
if (use_vrf)
json_vrf = json_object_new_object();
else
json_vrf = json;
json_nbr_array = json_object_new_array();
}
if (ospf->instance) {
@ -4303,9 +4322,19 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (!use_json)
show_ip_ospf_neighbour_header(vty);
else
json_object_object_add(json_vrf, "neighbors",
json_nbr_array);
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
show_ip_ospf_neighbor_sub(vty, oi, json_vrf, use_json);
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
if (ospf_interface_neighbor_count(oi) == 0)
continue;
if (use_json) {
json_nbr_sub = json_object_new_object();
json_object_array_add(json_nbr_array, json_nbr_sub);
}
show_ip_ospf_neighbor_sub(vty, oi, json_nbr_sub, use_json);
}
if (use_json) {
if (use_vrf) {
@ -4681,7 +4710,6 @@ static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json, use_vrf);
/*ifp = if_lookup_by_name(argv[arg_base]->arg, ospf->vrf_id);*/
ifp = if_lookup_by_name_all_vrf(argv[arg_base]->arg);
if (!ifp) {
if (use_json)
@ -8099,7 +8127,7 @@ DEFUN (no_ip_ospf_area,
DEFUN (ospf_redistribute_source,
ospf_redistribute_source_cmd,
"redistribute " FRR_REDIST_STR_OSPFD " [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
"redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
REDIST_STR
FRR_REDIST_HELP_STR_OSPFD
"Metric for redistributed routes\n"
@ -8132,13 +8160,15 @@ DEFUN (ospf_redistribute_source,
if (!str2metric(argv[idx]->arg, &metric))
return CMD_WARNING_CONFIG_FAILED;
}
idx = 1;
/* Get metric type. */
else if (argv_find(argv, argc, "(1-2)", &idx)) {
if (argv_find(argv, argc, "(1-2)", &idx)) {
if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED;
}
idx = 1;
/* Get route-map */
else if (argv_find(argv, argc, "WORD", &idx)) {
if (argv_find(argv, argc, "WORD", &idx)) {
ospf_routemap_set(red, argv[idx]->arg);
} else
ospf_routemap_unset(red);
@ -8148,7 +8178,7 @@ DEFUN (ospf_redistribute_source,
DEFUN (no_ospf_redistribute_source,
no_ospf_redistribute_source_cmd,
"no redistribute " FRR_REDIST_STR_OSPFD " [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
"no redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
NO_STR
REDIST_STR
FRR_REDIST_HELP_STR_OSPFD
@ -8338,7 +8368,7 @@ DEFUN (no_ospf_distribute_list_out,
/* Default information originate. */
DEFUN (ospf_default_information_originate,
ospf_default_information_originate_cmd,
"default-information originate [<always|metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
"default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
"Control distribution of default information\n"
"Distribute a default route\n"
"Always advertise default route\n"
@ -8361,18 +8391,21 @@ DEFUN (ospf_default_information_originate,
/* Check whether "always" was specified */
if (argv_find(argv, argc, "always", &idx))
default_originate = DEFAULT_ORIGINATE_ALWAYS;
idx = 1;
/* Get metric value */
else if (argv_find(argv, argc, "(0-16777214)", &idx)) {
if (argv_find(argv, argc, "(0-16777214)", &idx)) {
if (!str2metric(argv[idx]->arg, &metric))
return CMD_WARNING_CONFIG_FAILED;
}
idx = 1;
/* Get metric type. */
else if (argv_find(argv, argc, "(1-2)", &idx)) {
if (argv_find(argv, argc, "(1-2)", &idx)) {
if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED;
}
idx = 1;
/* Get route-map */
else if (argv_find(argv, argc, "WORD", &idx))
if (argv_find(argv, argc, "WORD", &idx))
ospf_routemap_set(red, argv[idx]->arg);
else
ospf_routemap_unset(red);
@ -8383,7 +8416,7 @@ DEFUN (ospf_default_information_originate,
DEFUN (no_ospf_default_information_originate,
no_ospf_default_information_originate_cmd,
"no default-information originate [<always|metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
"no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
NO_STR
"Control distribution of default information\n"
"Distribute a default route\n"
@ -9496,9 +9529,9 @@ DEFUN (show_ip_ospf_route,
}
if (uj) {
/* Keep Non-pretty format */
vty_out(vty, "%s\n",
json_object_to_json_string_ext(json,
JSON_C_TO_STRING_PRETTY));
json_object_to_json_string(json));
json_object_free(json);
}
@ -9522,9 +9555,9 @@ DEFUN (show_ip_ospf_route,
if (ospf) {
ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf);
/* Keep Non-pretty format */
if (uj)
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
vty_out(vty, "%s\n", json_object_to_json_string(json));
}
if (uj)
@ -9583,7 +9616,7 @@ DEFUN (show_ip_ospf_vrfs,
for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
json_object *json_vrf = NULL;
const char *name = NULL;
int vrf_id_ui = 0;
int64_t vrf_id_ui = 0;
count++;
@ -9597,7 +9630,8 @@ DEFUN (show_ip_ospf_vrfs,
else
name = ospf->name;
vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) ? -1 : ospf->vrf_id;
vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) ? -1 :
(int64_t) ospf->vrf_id;
if (uj) {
json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
@ -10202,8 +10236,12 @@ static int config_write_ospf_distribute(struct vty *vty, struct ospf *ospf)
if (red->dmetric.value >= 0)
vty_out(vty, " metric %d",
red->dmetric.value);
if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1)
vty_out(vty, " metric-type 1");
else if (red->dmetric.type ==
EXTERNAL_METRIC_TYPE_2)
vty_out(vty, " metric-type 2");
if (ROUTEMAP_NAME(red))
vty_out(vty, " route-map %s",

View File

@ -389,6 +389,7 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -466,6 +467,7 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -487,6 +489,7 @@ void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -506,6 +509,7 @@ void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;

View File

@ -32,6 +32,7 @@
#include "log.h"
#include "sockunion.h" /* for inet_aton () */
#include "zclient.h"
#include "routemap.h"
#include "plist.h"
#include "sockopt.h"
#include "bfd.h"
@ -183,8 +184,7 @@ void ospf_router_id_update(struct ospf *ospf)
struct route_node *rn;
struct ospf_lsa *lsa;
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
{
LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
/* AdvRouter and Router ID is the same. */
if (IPV4_ADDR_SAME(&lsa->data->adv_router,
&ospf->router_id)) {
@ -241,7 +241,7 @@ static struct ospf *ospf_new(u_short instance, const char *name)
new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
vrf = vrf_lookup_by_name(new->name);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: Create new ospf instance with vrf_name %s vrf_id %d",
zlog_debug("%s: Create new ospf instance with vrf_name %s vrf_id %u",
__PRETTY_FUNCTION__, name, new->vrf_id);
if (vrf)
ospf_vrf_link(new, vrf);
@ -555,6 +555,20 @@ void ospf_terminate(void)
for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
ospf_finish(ospf);
/* Cleanup route maps */
route_map_add_hook(NULL);
route_map_delete_hook(NULL);
route_map_event_hook(NULL);
route_map_finish();
/* reverse prefix_list_init */
prefix_list_add_hook(NULL);
prefix_list_delete_hook(NULL);
prefix_list_reset();
/* Cleanup vrf info */
ospf_vrf_terminate();
/* Deliberately go back up, hopefully to thread scheduler, as
* One or more ospf_finish()'s may have deferred shutdown to a timer
* thread
@ -847,7 +861,6 @@ static void ospf_area_free(struct ospf_area *area)
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa);
ospf_opaque_type10_lsa_term(area);
ospf_lsdb_delete_all(area->lsdb);
ospf_lsdb_free(area->lsdb);
@ -2016,7 +2029,7 @@ void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf)
static int ospf_vrf_new(struct vrf *vrf)
{
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: VRF Created: %s(%d)", __PRETTY_FUNCTION__,
zlog_debug("%s: VRF Created: %s(%u)", __PRETTY_FUNCTION__,
vrf->name, vrf->vrf_id);
return 0;
@ -2026,7 +2039,7 @@ static int ospf_vrf_new(struct vrf *vrf)
static int ospf_vrf_delete(struct vrf *vrf)
{
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: VRF Deletion: %s(%d)", __PRETTY_FUNCTION__,
zlog_debug("%s: VRF Deletion: %s(%u)", __PRETTY_FUNCTION__,
vrf->name, vrf->vrf_id);
return 0;
@ -2039,7 +2052,7 @@ static int ospf_vrf_enable(struct vrf *vrf)
vrf_id_t old_vrf_id = VRF_DEFAULT;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: VRF %s id %d enabled",
zlog_debug("%s: VRF %s id %u enabled",
__PRETTY_FUNCTION__, vrf->name, vrf->vrf_id);
ospf = ospf_lookup_by_name(vrf->name);
@ -2048,7 +2061,7 @@ static int ospf_vrf_enable(struct vrf *vrf)
/* We have instance configured, link to VRF and make it "up". */
ospf_vrf_link(ospf, vrf);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf linked to vrf %s vrf_id %d (old id %d)",
zlog_debug("%s: ospf linked to vrf %s vrf_id %u (old id %u)",
__PRETTY_FUNCTION__, vrf->name, ospf->vrf_id,
old_vrf_id);

View File

@ -136,7 +136,7 @@ static int pim_vrf_new(struct vrf *vrf)
{
struct pim_instance *pim = pim_instance_init(vrf);
zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id);
zlog_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
if (pim == NULL) {
zlog_err("%s %s: pim class init failure ", __FILE__,
__PRETTY_FUNCTION__);
@ -159,7 +159,7 @@ static int pim_vrf_delete(struct vrf *vrf)
{
struct pim_instance *pim = vrf->info;
zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id);
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
pim_ssmpingd_destroy(pim);
pim_instance_terminate(pim);

View File

@ -47,40 +47,14 @@
void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
struct pim_nexthop_cache *pnc, int command)
{
struct stream *s;
struct prefix *p;
int ret;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return;
p = &(pnc->rpf.rpf_addr);
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, command, pim->vrf_id);
/* get update for all routes for a prefix */
stream_putc(s, 0);
stream_putw(s, PREFIX_FAMILY(p));
stream_putc(s, p->prefixlen);
switch (PREFIX_FAMILY(p)) {
case AF_INET:
stream_put_in_addr(s, &p->u.prefix4);
break;
case AF_INET6:
stream_put(s, &(p->u.prefix6), 16);
break;
default:
break;
}
stream_putw_at(s, 0, stream_get_endp(s));
ret = zclient_send_message(zclient);
ret = zclient_send_rnh(zclient, command, p, false, pim->vrf_id);
if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
if (PIM_DEBUG_PIM_NHT) {
char buf[PREFIX2STR_BUFFER];
prefix2str(p, buf, sizeof(buf));
@ -811,7 +785,7 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf));
zlog_debug(
"%s: NHT Update for %s(%s) num_nh %d num_pim_nh %d vrf:%d up %ld rp %d",
"%s: NHT Update for %s(%s) num_nh %d num_pim_nh %d vrf:%u up %ld rp %d",
__PRETTY_FUNCTION__, buf, pim->vrf->name, nexthop_num,
pnc->nexthop_num, vrf_id, pnc->upstream_hash->count,
listcount(pnc->rp_list));

View File

@ -80,7 +80,7 @@ static int pim_zebra_if_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
"%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
"%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
@ -130,7 +130,7 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
"%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
"%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
@ -158,7 +158,7 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
"%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
"%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
@ -213,7 +213,7 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
"%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
"%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
__PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp));
@ -293,7 +293,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
zlog_debug("%s: %s(%d) connected IP address %s flags %u %s",
zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
__PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
? "secondary"
@ -372,7 +372,7 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
zlog_debug(
"%s: %s(%d) disconnected IP address %s flags %u %s",
"%s: %s(%u) disconnected IP address %s flags %u %s",
__PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags,
CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
@ -765,8 +765,6 @@ void pim_zebra_init(void)
zlog_info("zclient_init cleared redistribution request");
}
zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
/* Request all redistribution */
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default)

View File

@ -22,7 +22,7 @@
%{!?with_multipath: %global with_multipath 256 }
%{!?frr_user: %global frr_user frr }
%{!?vty_group: %global vty_group frrvty }
%{!?with_fpm: %global with_fpm 0 }
%{!?with_fpm: %global with_fpm 1 }
%{!?with_watchfrr: %global with_watchfrr 1 }
%{!?with_bgp_vnc: %global with_bgp_vnc 0 }
%{!?with_pimd: %global with_pimd 1 }
@ -554,6 +554,9 @@ rm -rf %{buildroot}
%{_libdir}/lib*.so.0
%attr(755,root,root) %{_libdir}/lib*.so.0.*
%endif
%if %{with_fpm}
%attr(755,root,root) %{_libdir}/frr/modules/zebra_fpm.so
%endif
%attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so
%{_bindir}/*
%config(noreplace) /etc/frr/[!v]*.conf*

View File

@ -48,6 +48,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;

View File

@ -48,6 +48,7 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;

View File

@ -159,6 +159,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@ -180,6 +181,7 @@ void route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));

View File

@ -25,8 +25,9 @@
#include "privs.h"
#include "queue.h"
#include "filter.h"
#include "frr_pthread.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgpd.c"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_packet.h"
@ -1272,6 +1273,9 @@ static int handle_attr_test(struct aspath_tests *t)
struct aspath *asp;
size_t datalen;
bgp_pthreads_init();
frr_pthread_get(PTHREAD_KEEPALIVES)->running = true;
asp = make_aspath(t->segment->asdata, t->segment->len, 0);
peer.curr = stream_new(BGP_MAX_PACKET_SIZE);

View File

@ -27,8 +27,9 @@
#include "memory.h"
#include "queue.h"
#include "filter.h"
#include "frr_pthread.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgpd.c"
#include "bgpd/bgp_open.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_packet.h"
@ -915,6 +916,9 @@ int main(void)
vrf_init(NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
bgp_pthreads_init();
frr_pthread_get(PTHREAD_KEEPALIVES)->running = true;
if (fileno(stdout) >= 0)
tty = isatty(fileno(stdout));

View File

@ -434,7 +434,14 @@ end
new_ctx = False
log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys)
elif "vni " in line:
# The 'vni' keyword under 'router bgp X/address-family l2vpn evpn' creates
# a sub-context but the 'vni' keyword in other places (such as 'vrf BLUE')
# does not.
elif ("vni " in line and
len(ctx_keys) == 2 and
ctx_keys[0].startswith('router bgp') and
ctx_keys[1] == 'address-family l2vpn evpn'):
main_ctx_key = []
# Save old context first

View File

@ -46,6 +46,9 @@
DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy")
/* Destination for vtysh output */
FILE *outputfile;
/* Struct VTY. */
struct vty *vty;
@ -138,16 +141,25 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
bufvalid += nread;
end = memmem(buf, bufvalid - buf, terminator,
if (bufvalid - buf >= 4)
end = memmem(bufvalid - 4, 4, terminator,
sizeof(terminator));
if (end + sizeof(terminator) + 1 > bufvalid)
if (end && end + sizeof(terminator) + 1 > bufvalid)
/* found \0\0\0 but return code hasn't been read yet */
end = NULL;
if (end)
ret = end[sizeof(terminator)];
while (bufvalid > buf && (end > buf || !end)) {
/*
* calculate # bytes we have, up to & not including the
* terminator if present
*/
size_t textlen = (end ? end : bufvalid) - buf;
/* feed line processing callback if present */
while (callback && bufvalid > buf && (end > buf || !end)) {
textlen = (end ? end : bufvalid) - buf;
char *eol = memchr(buf, '\n', textlen);
if (eol)
/* line break */
@ -165,8 +177,7 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
/* continue reading */
break;
/* eol is at a line end now, either \n => \0 or \0\0\0
*/
/* eol is at line end now, either \n => \0 or \0\0\0 */
assert(eol && eol <= bufvalid);
if (fp) {
@ -186,6 +197,14 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
end -= eol - buf;
}
/* else if no callback, dump raw */
if (!callback) {
if (fp)
fwrite(buf, 1, textlen, fp);
memmove(buf, buf + textlen, bufvalid - buf - textlen);
bufvalid -= textlen;
}
if (bufvalid == buf + bufsz) {
char *new;
bufsz *= 2;
@ -375,21 +394,21 @@ static int vtysh_execute_func(const char *line, int pager)
fprintf(stdout, "%% Command incomplete.\n");
break;
case CMD_SUCCESS_DAEMON: {
/* FIXME: Don't open pager for exit commands. popen() causes
* problems
* if exited from vtysh at all. This hack shouldn't cause any
* problem
* but is really ugly. */
if (pager && vtysh_pager_name
/*
* FIXME: Don't open pager for exit commands. popen() causes
* problems if exited from vtysh at all. This hack shouldn't
* cause any problem but is really ugly.
*/
fp = outputfile;
if (pager && vtysh_pager_name && outputfile == stdout
&& (strncmp(line, "exit", 4) != 0)) {
fp = popen(vtysh_pager_name, "w");
if (fp == NULL) {
perror("popen failed for pager");
fp = stdout;
fp = outputfile;
} else
closepager = 1;
} else
fp = stdout;
}
if (!strcmp(cmd->string, "configure terminal")) {
for (i = 0; i < array_size(vtysh_client); i++) {
@ -405,7 +424,7 @@ static int vtysh_execute_func(const char *line, int pager)
if (vline == NULL) {
if (pager && vtysh_pager_name && fp
&& closepager) {
&& fp != outputfile && closepager) {
if (pclose(fp) == -1) {
perror("pclose failed for pager");
}
@ -455,7 +474,7 @@ static int vtysh_execute_func(const char *line, int pager)
(*cmd->func)(cmd, vty, 0, NULL);
}
}
if (pager && vtysh_pager_name && fp && closepager) {
if (pager && vtysh_pager_name && fp && closepager && fp != outputfile) {
if (pclose(fp) == -1) {
perror("pclose failed for pager");
}
@ -537,19 +556,19 @@ int vtysh_mark_file(const char *filename)
switch (vty->node) {
case LDP_IPV4_IFACE_NODE:
if (strncmp(vty_buf_copy, " ", 3)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_IPV4_NODE;
}
break;
case LDP_IPV6_IFACE_NODE:
if (strncmp(vty_buf_copy, " ", 3)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_IPV6_NODE;
}
break;
case LDP_PSEUDOWIRE_NODE:
if (strncmp(vty_buf_copy, " ", 2)) {
fprintf(stdout, " end\n");
fprintf(outputfile, " end\n");
vty->node = LDP_L2VPN_NODE;
}
break;
@ -558,7 +577,7 @@ int vtysh_mark_file(const char *filename)
}
if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
continue;
}
@ -566,7 +585,7 @@ int vtysh_mark_file(const char *filename)
vline = cmd_make_strvec(vty->buf);
if (vline == NULL) {
fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
continue;
}
@ -609,15 +628,15 @@ int vtysh_mark_file(const char *filename)
|| prev_node == BGP_IPV6M_NODE
|| prev_node == BGP_EVPN_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit-address-family\n");
fprintf(outputfile, "exit-address-family\n");
} else if ((prev_node == BGP_EVPN_VNI_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit-vni\n");
fprintf(outputfile, "exit-vni\n");
} else if ((prev_node == KEYCHAIN_KEY_NODE)
&& (tried == 1)) {
fprintf(stdout, "exit\n");
fprintf(outputfile, "exit\n");
} else if (tried) {
fprintf(stdout, "end\n");
fprintf(outputfile, "end\n");
}
}
/* If command didn't succeed in any node, continue with return
@ -667,12 +686,12 @@ int vtysh_mark_file(const char *filename)
u_int i;
int cmd_stat = CMD_SUCCESS;
fprintf(stdout, "%s", vty->buf);
fprintf(outputfile, "%s", vty->buf);
for (i = 0; i < array_size(vtysh_client); i++) {
if (cmd->daemon & vtysh_client[i].flag) {
cmd_stat = vtysh_client_execute(
&vtysh_client[i], vty->buf,
stdout);
outputfile);
if (cmd_stat != CMD_SUCCESS)
break;
}
@ -686,7 +705,7 @@ int vtysh_mark_file(const char *filename)
}
}
/* This is the end */
fprintf(stdout, "\nend\n");
fprintf(outputfile, "\nend\n");
vty_close(vty);
XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
@ -749,7 +768,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
if (cmd->daemon & vtysh_client[i].flag) {
cmd_stat = vtysh_client_execute(
&vtysh_client[i], vty->buf,
stdout);
outputfile);
/*
* CMD_WARNING - Can mean that the
* command was
@ -1854,7 +1873,7 @@ DEFUN (vtysh_show_thread,
fprintf(stdout, "Thread statistics for %s:\n",
vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}
return ret;
@ -1875,7 +1894,7 @@ DEFUN (vtysh_show_work_queues,
fprintf(stdout, "Work queue statistics for %s:\n",
vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}
@ -1905,7 +1924,7 @@ DEFUN (vtysh_show_work_queues_daemon,
}
ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n",
stdout);
outputfile);
return ret;
}
@ -1932,9 +1951,9 @@ static int show_per_daemon(const char *line, const char *headline)
for (i = 0; i < array_size(vtysh_client); i++)
if (vtysh_client[i].fd >= 0) {
fprintf(stdout, headline, vtysh_client[i].name);
fprintf(outputfile, headline, vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line,
stdout);
outputfile);
fprintf(stdout, "\n");
}
@ -2226,20 +2245,19 @@ DEFUN (vtysh_write_terminal,
{
u_int i;
char line[] = "do write terminal\n";
FILE *fp = NULL;
FILE *fp = outputfile;
if (vtysh_pager_name) {
if (fp == stdout && vtysh_pager_name) {
fp = popen(vtysh_pager_name, "w");
if (fp == NULL) {
perror("popen");
exit(1);
}
} else
fp = stdout;
}
vty_out(vty, "Building configuration...\n");
vty_out(vty, "\nCurrent configuration:\n");
vty_out(vty, "!\n");
fprintf(outputfile, "Building configuration...\n");
fprintf(outputfile, "\nCurrent configuration:\n");
fprintf(outputfile, "!\n");
for (i = 0; i < array_size(vtysh_client); i++)
if ((argc < 3)
@ -2251,7 +2269,7 @@ DEFUN (vtysh_write_terminal,
vtysh_config_dump(fp);
if (vtysh_pager_name && fp) {
if (vtysh_pager_name && fp && fp != outputfile) {
fflush(fp);
if (pclose(fp) == -1) {
perror("pclose");
@ -2260,7 +2278,7 @@ DEFUN (vtysh_write_terminal,
fp = NULL;
}
vty_out(vty, "end\n");
fprintf(outputfile, "end\n");
return CMD_SUCCESS;
}
@ -2429,7 +2447,7 @@ DEFUN (vtysh_write_memory,
char line[] = "do write memory\n";
u_int i;
fprintf(stdout,
fprintf(outputfile,
"Note: this version of vtysh never writes vtysh.conf\n");
/* If integrated frr.conf explicitely set. */
@ -2441,7 +2459,7 @@ DEFUN (vtysh_write_memory,
if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1)
ret = vtysh_client_execute(&vtysh_client[i],
"do write integrated",
stdout);
outputfile);
if (ret != CMD_SUCCESS) {
printf("\nWarning: attempting direct configuration write without "
@ -2452,10 +2470,10 @@ DEFUN (vtysh_write_memory,
return ret;
}
fprintf(stdout, "Building Configuration...\n");
fprintf(outputfile, "Building Configuration...\n");
for (i = 0; i < array_size(vtysh_client); i++)
ret = vtysh_client_execute(&vtysh_client[i], line, stdout);
ret = vtysh_client_execute(&vtysh_client[i], line, outputfile);
return ret;
}
@ -2484,7 +2502,7 @@ DEFUN (vtysh_terminal_length,
lines = strtol(argv[idx_number]->arg, &endptr, 10);
if (lines < 0 || lines > 512 || *endptr != '\0') {
vty_out(vty, "length is malformed\n");
fprintf(outputfile, "length is malformed\n");
return CMD_WARNING;
}
@ -2527,8 +2545,8 @@ DEFUN (vtysh_show_daemons,
for (i = 0; i < array_size(vtysh_client); i++)
if (vtysh_client[i].fd >= 0)
vty_out(vty, " %s", vtysh_client[i].name);
vty_out(vty, "\n");
fprintf(outputfile, " %s", vtysh_client[i].name);
fprintf(outputfile, "\n");
return CMD_SUCCESS;
}
@ -2703,6 +2721,38 @@ DEFUN (config_list,
return cmd_list_cmds(vty, argc == 2);
}
DEFUN (vtysh_output_file,
vtysh_output_file_cmd,
"output file FILE",
"Direct vtysh output to file\n"
"Direct vtysh output to file\n"
"Path to dump output to\n")
{
const char *path = argv[argc - 1]->arg;
outputfile = fopen(path, "a");
if (!outputfile) {
fprintf(stdout, "Failed to open file '%s': %s\n", path,
safe_strerror(errno));
outputfile = stdout;
}
return CMD_SUCCESS;
}
DEFUN (no_vtysh_output_file,
no_vtysh_output_file_cmd,
"no output file [FILE]",
NO_STR
"Direct vtysh output to file\n"
"Direct vtysh output to file\n"
"Path to dump output to\n")
{
if (outputfile != stdout) {
fclose(outputfile);
outputfile = stdout;
}
return CMD_SUCCESS;
}
DEFUN(find,
find_cmd,
"find COMMAND...",
@ -2736,6 +2786,8 @@ static void vtysh_install_default(enum node_type node)
{
install_element(node, &config_list_cmd);
install_element(node, &find_cmd);
install_element(node, &vtysh_output_file_cmd);
install_element(node, &no_vtysh_output_file_cmd);
}
/* Making connection to protocol daemon. */
@ -2964,6 +3016,12 @@ static const struct cmd_variable_handler vtysh_var_handler[] = {
.completions = vtysh_autocomplete},
{.completions = NULL}};
void vtysh_uninit()
{
if (outputfile != stdout)
fclose(outputfile);
}
void vtysh_init_vty(void)
{
/* Make vty structure. */
@ -2971,6 +3029,9 @@ void vtysh_init_vty(void)
vty->type = VTY_SHELL;
vty->node = VIEW_NODE;
/* set default output */
outputfile = stdout;
/* Initialize commands. */
cmd_init(0);
cmd_variable_handler_register(vtysh_var_handler);

View File

@ -63,6 +63,7 @@ extern char frr_config[];
extern char vtydir[];
void vtysh_init_vty(void);
void vtysh_uninit(void);
void vtysh_init_cmd(void);
extern int vtysh_connect_all(const char *optional_daemon_name);
void vtysh_readline_init(void);

View File

@ -644,6 +644,8 @@ int main(int argc, char **argv, char **env)
while (vtysh_rl_gets())
vtysh_execute(line_read);
vtysh_uninit();
history_truncate_file(history_file, 1000);
printf("\n");

View File

@ -238,10 +238,12 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break;
}
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ifp->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ifp->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {

View File

@ -387,6 +387,11 @@ static int get_iflink_speed(const char *ifname)
return (ecmd.speed_hi << 16) | ecmd.speed;
}
uint32_t kernel_get_speed(struct interface *ifp)
{
return get_iflink_speed(ifp->name);
}
static int netlink_extract_bridge_info(struct rtattr *link_data,
struct zebra_l2info_bridge *bridge_info)
{

View File

@ -57,8 +57,29 @@ DEFINE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),
DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp),
(vty, ifp))
static void if_down_del_nbr_connected(struct interface *ifp);
static int if_zebra_speed_update(struct thread *thread)
{
struct interface *ifp = THREAD_ARG(thread);
struct zebra_if *zif = ifp->info;
uint32_t new_speed;
zif->speed_update = NULL;
new_speed = kernel_get_speed(ifp);
if (new_speed != ifp->speed) {
zlog_info("%s: %s old speed: %u new speed: %u",
__PRETTY_FUNCTION__, ifp->name,
ifp->speed, new_speed);
ifp->speed = new_speed;
if_add_update(ifp);
}
return 1;
}
static void zebra_if_node_destroy(route_table_delegate_t *delegate,
struct route_table *table,
struct route_node *node)
@ -119,6 +140,16 @@ static int if_zebra_new_hook(struct interface *ifp)
route_table_init_with_delegate(&zebra_if_table_delegate);
ifp->info = zebra_if;
/*
* Some platforms are telling us that the interface is
* up and ready to go. When we check the speed we
* sometimes get the wrong value. Wait a couple
* of seconds and ask again. Hopefully it's all settled
* down upon startup.
*/
thread_add_timer(zebrad.master, if_zebra_speed_update,
ifp, 15, &zebra_if->speed_update);
return 0;
}
@ -141,6 +172,8 @@ static int if_zebra_delete_hook(struct interface *ifp)
list_delete_and_null(&rtadv->AdvPrefixList);
#endif /* HAVE_RTADV */
THREAD_OFF(zebra_if->speed_update);
XFREE(MTYPE_TMP, zebra_if);
}
@ -735,6 +768,7 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
zebra_interface_vrf_update_add(ifp, old_vrf_id);
/* Install connected routes (in new VRF). */
if (if_is_operative(ifp))
if_install_connected(ifp);
static_ifindex_update(ifp, true);

View File

@ -273,6 +273,8 @@ struct zebra_if {
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
struct thread *speed_update;
};
DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),

View File

@ -1048,7 +1048,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else
@ -1096,7 +1096,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else

View File

@ -121,7 +121,7 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
s = zserv->obuf;
stream_reset(s);
zserv_create_header(s, cmd, vrf_id);
zclient_create_header(s, cmd, vrf_id);
/* result */
stream_putc(s, 1);

View File

@ -300,6 +300,13 @@ int main(int argc, char **argv)
zebra_if_init();
zebra_debug_init();
router_id_cmd_init();
/*
* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
zebra_ns_init();
zebra_vty_init();
access_list_init();
prefix_list_init();
#if defined(HAVE_RTADV)
@ -317,16 +324,6 @@ int main(int argc, char **argv)
/* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
/* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
zebra_ns_init();
/*
* Initialize show/config command after the vrf initialization is
* complete
*/
zebra_vty_init();
#if defined(HANDLE_ZAPI_FUZZING)
if (fuzzing) {
zserv_read_file(fuzzing);

View File

@ -59,6 +59,7 @@ struct route_entry {
/* VRF identifier. */
vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
/* Which routing table */
uint32_t table;
@ -293,8 +294,8 @@ extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
/* NOTE:
* All rib_add function will not just add prefix into RIB, but
* also implicitly withdraw equal prefix of same type. */
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
u_short instance, int flags, struct prefix *p,
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
int type, u_short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
uint8_t distance, route_tag_t tag);
@ -439,6 +440,8 @@ DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason),
extern void zebra_vty_init(void);
extern int static_config(struct vty *vty, struct zebra_vrf *zvrf,
afi_t afi, safi_t safi, const char *cmd);
extern pid_t pid;
#endif /*_ZEBRA_RIB_H */

View File

@ -60,15 +60,17 @@ enum southbound_results {
* semantics so we will end up with a delete than
* a re-add.
*/
extern void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new);
extern void kernel_route_rib(struct route_node *rn, struct prefix *p,
struct prefix *src_p, struct route_entry *old,
struct route_entry *new);
/*
* So route install/failure may not be immediately known
* so let's separate it out and allow the result to
* be passed back up.
*/
extern void kernel_route_rib_pass_fail(struct prefix *p,
extern void kernel_route_rib_pass_fail(struct route_node *rn,
struct prefix *p,
struct route_entry *re,
enum southbound_results res);
@ -98,6 +100,7 @@ extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp,
extern int mpls_kernel_init(void);
extern uint32_t kernel_get_speed(struct interface *ifp);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);

View File

@ -403,6 +403,9 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) {
struct interface *ifp;
vrf_id_t nh_vrf_id = vrf_id;
if (!tb[RTA_MULTIPATH]) {
struct nexthop nh;
size_t sz = (afi == AFI_IP) ? 4 : 16;
@ -434,7 +437,14 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_add(afi, SAFI_UNICAST, vrf_id, proto,
if (index) {
ifp = if_lookup_by_index(index,
VRF_UNKNOWN);
if (ifp)
nh_vrf_id = ifp->vrf_id;
}
rib_add(afi, SAFI_UNICAST, vrf_id, nh_vrf_id, proto,
0, flags, &p, NULL, &nh, table, metric,
mtu, distance, tag);
} else {
@ -453,6 +463,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
re->metric = metric;
re->mtu = mtu;
re->vrf_id = vrf_id;
re->nh_vrf_id = vrf_id;
re->table = table;
re->nexthop_num = 0;
re->uptime = time(NULL);
@ -464,6 +475,18 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
break;
index = rtnh->rtnh_ifindex;
if (index) {
/*
* Yes we are looking this up
* for every nexthop and just
* using the last one looked
* up right now
*/
ifp = if_lookup_by_index(index,
VRF_UNKNOWN);
if (ifp)
re->nh_vrf_id = ifp->vrf_id;
}
gate = 0;
if (rtnh->rtnh_len > sizeof(*rtnh)) {
memset(tb, 0, sizeof(tb));
@ -803,7 +826,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
struct rtmsg *rtmsg,
size_t req_size, int cmd)
{
struct nexthop_label *nh_label;
struct mpls_label_stack *nh_label;
mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
@ -940,10 +963,17 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
/*
* We have the ifindex so we should always send it
* This is especially useful if we are doing route
* leaking.
*/
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
if (cmd == RTM_NEWROUTE) {
if (nexthop->rmap_src.ipv4.s_addr)
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@ -961,8 +991,6 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
}
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (cmd == RTM_NEWROUTE) {
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@ -1003,7 +1031,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
struct rtmsg *rtmsg,
union g_addr **src)
{
struct nexthop_label *nh_label;
struct mpls_label_stack *nh_label;
mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
@ -1141,11 +1169,18 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
/*
* We have figured out the ifindex so we should always send it
* This is especially useful if we are doing route
* leaking.
*/
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
rtnh->rtnh_ifindex = nexthop->ifindex;
/* ifindex */
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (nexthop->rmap_src.ipv4.s_addr)
*src = &nexthop->rmap_src;
else if (nexthop->src.ipv4.s_addr)
@ -1157,8 +1192,6 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
"nexthop via if %u",
routedesc, nexthop->ifindex);
} else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"netlink_route_multipath() (%s): "
@ -1609,8 +1642,9 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
return suc;
}
void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new)
void kernel_route_rib(struct route_node *rn, struct prefix *p,
struct prefix *src_p, struct route_entry *old,
struct route_entry *new)
{
int ret = 0;
@ -1639,7 +1673,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
ret = netlink_route_multipath(RTM_NEWROUTE, p,
src_p, new, 0);
}
kernel_route_rib_pass_fail(p, new,
kernel_route_rib_pass_fail(rn, p, new,
(!ret) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
@ -1649,7 +1683,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
if (old) {
ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
kernel_route_rib_pass_fail(p, old,
kernel_route_rib_pass_fail(rn, p, old,
(!ret) ?
SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE);

View File

@ -67,7 +67,7 @@ static int sin_masklen(struct in_addr mask)
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
#ifdef __OpenBSD__
static int kernel_rtm_add_labels(struct nexthop_label *nh_label,
static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label,
struct sockaddr_mpls *smpls)
{
if (nh_label->num_labels > 1) {
@ -387,8 +387,9 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re)
return 0;
}
void kernel_route_rib(struct prefix *p, struct prefix *src_p,
struct route_entry *old, struct route_entry *new)
void kernel_route_rib(struct route_node *rn, struct prefix *p,
struct prefix *src_p, struct route_entry *old,
struct route_entry *new)
{
int route = 0;
@ -410,12 +411,12 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
zlog_err("Can't lower privileges");
if (new) {
kernel_route_rib_pass_fail(p, new,
kernel_route_rib_pass_fail(rn, p, new,
(!route) ?
SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE);
} else {
kernel_route_rib_pass_fail(p, old,
kernel_route_rib_pass_fail(rn, p, old,
(!route) ?
SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE);
@ -473,4 +474,9 @@ extern int kernel_interface_set_master(struct interface *master,
return 0;
}
uint32_t kernel_get_speed(struct interface *ifp)
{
return ifp->speed;
}
#endif /* !HAVE_NETLINK */

View File

@ -97,8 +97,9 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0);
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, NULL,
&nh, 0, 0, 0, 0, 0);
}
void route_read(struct zebra_ns *zns)

View File

@ -713,6 +713,14 @@ static int zfpm_read_cb(struct thread *thread)
nbyte = stream_read_try(ibuf, zfpm_g->sock,
FPM_MSG_HDR_LEN - already);
if (nbyte == 0 || nbyte == -1) {
if (nbyte == -1) {
char buffer[1024];
sprintf(buffer, "closed socket in read(%d): %s",
errno, safe_strerror(errno));
zfpm_connection_down(buffer);
}
else
zfpm_connection_down("closed socket in read");
return 0;
}
@ -743,6 +751,14 @@ static int zfpm_read_cb(struct thread *thread)
nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already);
if (nbyte == 0 || nbyte == -1) {
if (nbyte == -1) {
char buffer[1024];
sprintf(buffer, "failed to read message(%d) %s",
errno, safe_strerror(errno));
zfpm_connection_down(buffer);
}
else
zfpm_connection_down("failed to read message");
return 0;
}

View File

@ -104,7 +104,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
ifindex_t ifindex, mpls_label_t out_label);
static int nhlfe_del(zebra_nhlfe_t *snhlfe);
static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
struct nexthop_label *nh_label);
struct mpls_label_stack *nh_label);
static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type);
static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf,
@ -457,7 +457,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
s = client->obuf;
stream_reset(s);
zserv_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT);
zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT);
stream_putw(s, rn->p.family);
stream_put_prefix(s, &rn->p);
@ -1217,7 +1217,7 @@ static int nhlfe_del(zebra_nhlfe_t *nhlfe)
* Update label for NHLFE entry.
*/
static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
struct nexthop_label *nh_label)
struct mpls_label_stack *nh_label)
{
nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
}

View File

@ -61,7 +61,7 @@ stream_failure:
stream_reset(s);
zserv_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf));
zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf));
stream_put_in_addr(s, &mroute.sg.src);
stream_put_in_addr(s, &mroute.sg.grp);
stream_put(s, &mroute.lastused, sizeof(mroute.lastused));

View File

@ -81,7 +81,7 @@ int zebra_ns_init(void)
zebra_vrf_init();
zebra_ns_enable(0, (void **)&dzns);
zebra_ns_enable(NS_DEFAULT, (void **)&dzns);
return 0;
}

View File

@ -57,9 +57,6 @@ struct zebra_ns {
#endif /* HAVE_RTADV */
};
#define NS_DEFAULT 0
#define NS_UNKNOWN UINT16_MAX
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id);
int zebra_ns_init(void);

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