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 - SUBGRP_FOREACH_ADJ_SAFE
- AF_FOREACH - AF_FOREACH
- FOREACH_AFI_SAFI - 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 FRRouting is free software that implements and manages various IPv4 and IPv6
protocols. routing protocols.
Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, Currently FRRouting supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng,
RIPv2, RIPng, PIM-SM/MSDP and LDP as well as very early support for IS-IS, IS-IS, PIM-SM/MSDP, LDP and Babel as well as very early support for EIGRP and
EIGRP and NHRP. NHRP.
See the file REPORTING-BUGS to report bugs. 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. Free RRRouting is free software. See the file COPYING for copying conditions.
Public email discussion can be found at https://lists.frrouting.org/listinfo 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.type = ZEBRA_ROUTE_BABEL;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = quagga_prefix; api.prefix = quagga_prefix;
if(metric >= KERNEL_INFINITY) { 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);
BGP_ADV_FIFO_INIT(&sync->withdraw_low); BGP_ADV_FIFO_INIT(&sync->withdraw_low);
peer->sync[afi][safi] = sync; 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]) if (peer->sync[afi][safi])
XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL; 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])); prefix2str(&dp, buf[0], sizeof(buf[0]));
if (ifp) { if (ifp) {
zlog_debug( 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], vrf_id, ifp->name, buf[0],
bfd_get_status_str(status)); bfd_get_status_str(status));
} else { } else {
prefix2str(&sp, buf[1], sizeof(buf[1])); prefix2str(&sp, buf[1], sizeof(buf[1]));
zlog_debug( 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], vrf_id, buf[1], buf[0],
bfd_get_status_str(status)); 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_TRANS_ERR (1 << 0) // EAGAIN or similar occurred
#define BGP_IO_FATAL_ERR (1 << 1) // some kind of fatal TCP error #define BGP_IO_FATAL_ERR (1 << 1) // some kind of fatal TCP error
/* Start and stop routines for I/O pthread + control variables /* Thread external API ----------------------------------------------------- */
* ------------------------------------------------------------------------ */
_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();
}
void bgp_writes_on(struct peer *peer) 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->status != Deleted);
assert(peer->obuf); assert(peer->obuf);
assert(peer->ibuf); assert(peer->ibuf);
@ -127,8 +66,6 @@ void bgp_writes_on(struct peer *peer)
assert(!peer->t_connect_check_w); assert(!peer->t_connect_check_w);
assert(peer->fd); assert(peer->fd);
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
thread_add_write(fpt->master, bgp_process_writes, peer, peer->fd, thread_add_write(fpt->master, bgp_process_writes, peer, peer->fd,
&peer->t_write); &peer->t_write);
SET_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON); 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) void bgp_writes_off(struct peer *peer)
{ {
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
thread_cancel_async(fpt->master, &peer->t_write, NULL); thread_cancel_async(fpt->master, &peer->t_write, NULL);
THREAD_OFF(peer->t_generate_updgrp_packets); 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) 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->status != Deleted);
assert(peer->ibuf); assert(peer->ibuf);
assert(peer->fd); assert(peer->fd);
@ -155,8 +96,6 @@ void bgp_reads_on(struct peer *peer)
assert(!peer->t_connect_check_w); assert(!peer->t_connect_check_w);
assert(peer->fd); assert(peer->fd);
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd, thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
&peer->t_read); &peer->t_read);
@ -166,6 +105,7 @@ void bgp_reads_on(struct peer *peer)
void bgp_reads_off(struct peer *peer) void bgp_reads_off(struct peer *peer)
{ {
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
assert(fpt->running);
thread_cancel_async(fpt->master, &peer->t_read, NULL); thread_cancel_async(fpt->master, &peer->t_read, NULL);
THREAD_OFF(peer->t_process_packet); 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); 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. * Called from I/O pthread when a file descriptor has become ready for writing.
*/ */
static int bgp_process_writes(struct thread *thread) 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); 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)) { if (CHECK_FLAG(status, BGP_IO_FATAL_ERR)) {
reschedule = false; /* problem */ reschedule = false;
fatal = true; fatal = true;
} }
@ -217,7 +159,7 @@ static int bgp_process_writes(struct thread *thread)
return 0; return 0;
} }
/** /*
* Called from I/O pthread when a file descriptor has become ready for reading, * Called from I/O pthread when a file descriptor has become ready for reading,
* or has hung up. * or has hung up.
* *
@ -288,8 +230,10 @@ static int bgp_process_reads(struct thread *thread)
/* if this fails we are seriously screwed */ /* if this fails we are seriously screwed */
assert(pktsize <= BGP_MAX_PACKET_SIZE); 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) { if (ringbuf_remain(ibw) >= pktsize) {
struct stream *pkt = stream_new(pktsize); struct stream *pkt = stream_new(pktsize);
assert(ringbuf_get(ibw, pktbuf, pktsize) == pktsize); assert(ringbuf_get(ibw, pktbuf, pktsize) == pktsize);
@ -323,7 +267,7 @@ static int bgp_process_reads(struct thread *thread)
return 0; return 0;
} }
/** /*
* Flush peer output buffer. * Flush peer output buffer.
* *
* This function pops packets off of peer->obuf and writes them to peer->fd. * 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 num;
int update_last_write = 0; int update_last_write = 0;
unsigned int count = 0; unsigned int count = 0;
uint32_t oc; uint32_t uo = 0;
uint32_t uo;
uint16_t status = 0; uint16_t status = 0;
uint32_t wpkt_quanta_old; 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 = wpkt_quanta_old =
atomic_load_explicit(&peer->bgp->wpkt_quanta, memory_order_relaxed); atomic_load_explicit(&peer->bgp->wpkt_quanta, memory_order_relaxed);
@ -369,7 +308,7 @@ static uint16_t bgp_write(struct peer *peer)
} }
goto done; goto done;
} else if (num != writenum) // incomplete write } else if (num != writenum)
stream_forward_getp(s, num); stream_forward_getp(s, num);
} while (num != writenum); } while (num != writenum);
@ -386,6 +325,7 @@ static uint16_t bgp_write(struct peer *peer)
case BGP_MSG_UPDATE: case BGP_MSG_UPDATE:
atomic_fetch_add_explicit(&peer->update_out, 1, atomic_fetch_add_explicit(&peer->update_out, 1,
memory_order_relaxed); memory_order_relaxed);
uo++;
break; break;
case BGP_MSG_NOTIFY: case BGP_MSG_NOTIFY:
atomic_fetch_add_explicit(&peer->notify_out, 1, 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)) if (peer->v_start >= (60 * 2))
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); BGP_EVENT_ADD(peer, BGP_Stop);
goto done; goto done;
@ -424,9 +366,12 @@ static uint16_t bgp_write(struct peer *peer)
} }
done : { done : {
/* Update last_update if UPDATEs were written. */ /*
uo = atomic_load_explicit(&peer->update_out, memory_order_relaxed); * Update last_update if UPDATEs were written.
if (uo > oc) * 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(), atomic_store_explicit(&peer->last_update, bgp_clock(),
memory_order_relaxed); memory_order_relaxed);
@ -439,7 +384,7 @@ done : {
return status; return status;
} }
/** /*
* Reads a chunk of data from peer->fd into peer->ibuf_work. * Reads a chunk of data from peer->fd into peer->ibuf_work.
* *
* @return status flag (see top-of-file) * @return status flag (see top-of-file)

View File

@ -28,24 +28,6 @@
#include "bgpd/bgpd.h" #include "bgpd/bgpd.h"
#include "frr_pthread.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. * Start function for write thread.
* *

View File

@ -36,14 +36,14 @@
#include "bgpd/bgp_keepalives.h" #include "bgpd/bgp_keepalives.h"
/* clang-format on */ /* clang-format on */
/** /*
* Peer KeepAlive Timer. * Peer KeepAlive Timer.
* Associates a peer with the time of its last keepalive. * Associates a peer with the time of its last keepalive.
*/ */
struct pkat { struct pkat {
// the peer to send keepalives to /* the peer to send keepalives to */
struct peer *peer; struct peer *peer;
// absolute time of last keepalive sent /* absolute time of last keepalive sent */
struct timeval last; struct timeval last;
}; };
@ -52,9 +52,6 @@ static pthread_mutex_t *peerhash_mtx;
static pthread_cond_t *peerhash_cond; static pthread_cond_t *peerhash_cond;
static struct hash *peerhash; static struct hash *peerhash;
/* Thread control flag. */
bool bgp_keepalives_thread_run = false;
static struct pkat *pkat_new(struct peer *peer) static struct pkat *pkat_new(struct peer *peer)
{ {
struct pkat *pkat = XMALLOC(MTYPE_TMP, sizeof(struct pkat)); 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}; static struct timeval tolerance = {0, 100000};
// calculate elapsed time since last keepalive /* calculate elapsed time since last keepalive */
monotime_since(&pkat->last, &elapsed); 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; ka.tv_sec = pkat->peer->v_keepalive;
timersub(&ka, &elapsed, &diff); timersub(&ka, &elapsed, &diff);
@ -118,10 +115,10 @@ static void peer_process(struct hash_backet *hb, void *arg)
bgp_keepalive_send(pkat->peer); bgp_keepalive_send(pkat->peer);
monotime(&pkat->last); monotime(&pkat->last);
memset(&elapsed, 0x00, sizeof(struct timeval)); 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, <)) if (next_update->tv_sec <= 0 || timercmp(&diff, next_update, <))
*next_update = diff; *next_update = diff;
} }
@ -139,29 +136,9 @@ static unsigned int peer_hash_key(void *arg)
return (uintptr_t)pkat->peer; return (uintptr_t)pkat->peer;
} }
void bgp_keepalives_init() /* Cleanup handler / deinitializer. */
{
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);
}
static void bgp_keepalives_finish(void *arg) static void bgp_keepalives_finish(void *arg)
{ {
bgp_keepalives_thread_run = false;
if (peerhash) { if (peerhash) {
hash_clean(peerhash, pkat_del); hash_clean(peerhash, pkat_del);
hash_free(peerhash); hash_free(peerhash);
@ -177,32 +154,50 @@ static void bgp_keepalives_finish(void *arg)
XFREE(MTYPE_TMP, peerhash_cond); XFREE(MTYPE_TMP, peerhash_cond);
} }
/** /*
* Entry function for peer keepalive generation pthread. * Entry function for peer keepalive generation pthread.
*
* bgp_keepalives_init() must be called prior to this.
*/ */
void *bgp_keepalives_start(void *arg) void *bgp_keepalives_start(void *arg)
{ {
struct frr_pthread *fpt = arg;
fpt->master->owner = pthread_self();
struct timeval currtime = {0, 0}; struct timeval currtime = {0, 0};
struct timeval aftertime = {0, 0}; struct timeval aftertime = {0, 0};
struct timeval next_update = {0, 0}; struct timeval next_update = {0, 0};
struct timespec next_update_ts = {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); pthread_mutex_lock(peerhash_mtx);
// register cleanup handler /* register cleanup handler */
pthread_cleanup_push(&bgp_keepalives_finish, NULL); 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) if (peerhash->count > 0)
pthread_cond_timedwait(peerhash_cond, peerhash_mtx, pthread_cond_timedwait(peerhash_cond, peerhash_mtx,
&next_update_ts); &next_update_ts);
else else
while (peerhash->count == 0 while (peerhash->count == 0
&& bgp_keepalives_thread_run) && atomic_load_explicit(&fpt->running,
memory_order_relaxed))
pthread_cond_wait(peerhash_cond, peerhash_mtx); pthread_cond_wait(peerhash_cond, peerhash_mtx);
monotime(&currtime); monotime(&currtime);
@ -219,7 +214,7 @@ void *bgp_keepalives_start(void *arg)
TIMEVAL_TO_TIMESPEC(&next_update, &next_update_ts); TIMEVAL_TO_TIMESPEC(&next_update, &next_update_ts);
} }
// clean up /* clean up */
pthread_cleanup_pop(1); pthread_cleanup_pop(1);
return NULL; return NULL;
@ -229,6 +224,12 @@ void *bgp_keepalives_start(void *arg)
void bgp_keepalives_on(struct peer *peer) 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 */ /* placeholder bucket data to use for fast key lookups */
static struct pkat holder = {0}; static struct pkat holder = {0};
@ -253,6 +254,12 @@ void bgp_keepalives_on(struct peer *peer)
void bgp_keepalives_off(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 */ /* placeholder bucket data to use for fast key lookups */
static struct pkat holder = {0}; static struct pkat holder = {0};
@ -283,10 +290,13 @@ void bgp_keepalives_wake()
pthread_mutex_unlock(peerhash_mtx); 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(); bgp_keepalives_wake();
pthread_join(fpt->thread, result); pthread_join(fpt->thread, result);
return 0; return 0;
} }

View File

@ -88,6 +88,6 @@ extern void bgp_keepalives_wake(void);
/** /**
* Stops the thread and blocks until it terminates. * 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 */ #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) static int bgp_vrf_new(struct vrf *vrf)
{ {
if (BGP_DEBUG(zebra, ZEBRA)) 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; return 0;
} }
@ -240,7 +240,7 @@ static int bgp_vrf_new(struct vrf *vrf)
static int bgp_vrf_delete(struct vrf *vrf) static int bgp_vrf_delete(struct vrf *vrf)
{ {
if (BGP_DEBUG(zebra, ZEBRA)) 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; return 0;
} }
@ -251,7 +251,7 @@ static int bgp_vrf_enable(struct vrf *vrf)
vrf_id_t old_vrf_id; vrf_id_t old_vrf_id;
if (BGP_DEBUG(zebra, ZEBRA)) 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); bgp = bgp_lookup_by_name(vrf->name);
if (bgp) { 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); bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) { if (!bgp) {
zlog_err( zlog_err(
"parse nexthop update: instance not found for vrf_id %d", "parse nexthop update: instance not found for vrf_id %u",
vrf_id); vrf_id);
return; return;
} }
@ -389,7 +389,7 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf)); prefix2str(&p, buf, sizeof(buf));
zlog_debug( 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, vrf_id, buf, metric, bnc->metric, nexthop_num,
bnc->nexthop_num, bnc->flags); 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) static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
{ {
struct stream *s;
struct prefix *p; struct prefix *p;
bool exact_match = false;
int ret; int ret;
/* Check socket. */ if (!zclient)
if (!zclient || zclient->sock < 0)
return; return;
/* Don't try to register if Zebra doesn't know of this instance. */ /* 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; return;
p = &(bnc->node->p); p = &(bnc->node->p);
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, command, bnc->bgp->vrf_id);
if ((command == ZEBRA_NEXTHOP_REGISTER || if ((command == ZEBRA_NEXTHOP_REGISTER ||
command == ZEBRA_IMPORT_ROUTE_REGISTER) && command == ZEBRA_IMPORT_ROUTE_REGISTER) &&
(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
|| CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))) || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
stream_putc(s, 1); exact_match = true;
else
stream_putc(s, 0);
stream_putw(s, PREFIX_FAMILY(p)); ret = zclient_send_rnh(zclient, command, p,
stream_putc(s, p->prefixlen); exact_match, bnc->bgp->vrf_id);
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);
/* TBD: handle the failure */ /* TBD: handle the failure */
if (ret < 0) if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); 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); 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) static int bgp_write_notify(struct peer *peer)
{ {
int ret, val; int ret, val;
u_char type; u_char type;
struct stream *s; struct stream *s;
pthread_mutex_lock(&peer->io_mtx); /* There should be at least one packet. */
{ s = stream_fifo_pop(peer->obuf);
/* There should be at least one packet. */
s = stream_fifo_pop(peer->obuf);
}
pthread_mutex_unlock(&peer->io_mtx);
if (!s) if (!s)
return 0; 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 * This function attempts to write the packet from the thread it is called
* from, to ensure the packet gets out ASAP. * 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 peer
* @param code BGP error code * @param code BGP error code
* @param sub_code BGP error subcode * @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; struct stream *s;
int length; int length;
/* Lock I/O mutex to prevent other threads from pushing packets */
pthread_mutex_lock(&peer->io_mtx);
/* ============================================== */
/* Allocate new stream. */ /* Allocate new stream. */
s = stream_new(BGP_MAX_PACKET_SIZE); 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. */ /* Set BGP packet length. */
length = bgp_packet_set_size(s); 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 */ /* wipe output buffer */
pthread_mutex_lock(&peer->io_mtx); stream_fifo_clean(peer->obuf);
{
stream_fifo_clean(peer->obuf);
}
pthread_mutex_unlock(&peer->io_mtx);
/* /*
* If possible, store last packet for debugging purposes. This check is * 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; peer->last_reset = PEER_DOWN_NOTIFY_SEND;
/* Add packet to peer's output queue */ /* Add packet to peer's output queue */
bgp_packet_add(peer, s); stream_fifo_push(peer->obuf, s);
bgp_write_notify(peer); 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. */ /* AS path local-as loop check. */
if (peer->change_local_as) { 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; aspath_loop_count = 1;
if (aspath_loop_check(attr->aspath, peer->change_local_as) 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, vty_out(vty,
"{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
",\n \"routerId\": \"%s\",\n \"routes\": { ", ",\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->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default"
: bgp->name, : bgp->name,
table->version, inet_ntoa(bgp->router_id)); 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; struct bgp_node *rn, *next;
unsigned long output_cum = 0; unsigned long output_cum = 0;
unsigned long total_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) { for (rn = bgp_table_top(table); rn; rn = next) {
next = bgp_route_next(rn); 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, output_arg, use_json,
rd, next == NULL, rd, next == NULL,
&output_cum, &total_cum); &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) if (use_json)
vty_out(vty, " } }"); vty_out(vty, " } }");
return CMD_SUCCESS; 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, &bgp_static->gatewayIp.u.prefix, buf2,
sizeof(buf2)); sizeof(buf2));
vty_out(vty, 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, buf, rdbuf, p->u.prefix_evpn.eth_tag,
decode_label(&bgp_static->label), esi, buf2, decode_label(&bgp_static->label), esi, buf2,
macrouter); 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); 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, DEFUN (neighbor_remote_as,
neighbor_remote_as_cmd, neighbor_remote_as_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <(1-4294967295)|internal|external>", "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); return bgp_vty_return(vty, ret);
} }
DEFUN (neighbor_activate, DEFUN (neighbor_activate,
neighbor_activate_cmd, neighbor_activate_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> activate", "neighbor <A.B.C.D|X:X::X:X|WORD> activate",
@ -6490,7 +6502,6 @@ DEFUN (show_bgp_vrfs,
struct listnode *node, *nnode; struct listnode *node, *nnode;
int peers_cfg, peers_estb; int peers_cfg, peers_estb;
json_object *json_vrf = NULL; json_object *json_vrf = NULL;
int vrf_id_ui;
/* Skip Views. */ /* Skip Views. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
@ -6524,8 +6535,10 @@ DEFUN (show_bgp_vrfs,
type = "VRF"; type = "VRF";
} }
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id;
if (uj) { 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_string_add(json_vrf, "type", type);
json_object_int_add(json_vrf, "vrfId", vrf_id_ui); json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
json_object_string_add(json_vrf, "routerId", json_object_string_add(json_vrf, "routerId",
@ -6543,7 +6556,9 @@ DEFUN (show_bgp_vrfs,
} else } else
vty_out(vty, vty_out(vty,
"%4s %-5d %-16s %9u %10u %-37s %-10u %-15s\n", "%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, peers_cfg, peers_estb, name, bgp->l3vni,
prefix_mac2str(&bgp->rmac, buf, sizeof(buf))); 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) { if (!count) {
unsigned long ents; unsigned long ents;
char memstrbuf[MTYPE_MEMSTR_LEN]; char memstrbuf[MTYPE_MEMSTR_LEN];
int vrf_id_ui; int64_t vrf_id_ui;
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 */ /* Usage summary and header */
if (use_json) { 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, vty_out(vty,
"BGP router identifier %s, local AS number %u vrf-id %d", "BGP router identifier %s, local AS number %u vrf-id %d",
inet_ntoa(bgp->router_id), bgp->as, inet_ntoa(bgp->router_id), bgp->as,
vrf_id_ui); bgp->vrf_id == VRF_UNKNOWN ? -1 :
(int)bgp->vrf_id);
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
@ -9853,7 +9870,6 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
} }
if (use_json) { if (use_json) {
bgp_show_bestpath_json(bgp, json);
vty_out(vty, "%s\n", json_object_to_json_string_ext( vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY)); json, JSON_C_TO_STRING_PRETTY));
json_object_free(json); 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", json_object_int_add(json, "vrfId",
(bgp->vrf_id == VRF_UNKNOWN) (bgp->vrf_id == VRF_UNKNOWN)
? -1 ? -1 : (int64_t) bgp->vrf_id);
: bgp->vrf_id);
json_object_string_add( json_object_string_add(
json, "vrfName", json, "vrfName",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) (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, &bgp_listen_range_cmd);
install_element(BGP_NODE, &no_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. */ /* "neighbor remote-as" commands. */
install_element(BGP_NODE, &neighbor_remote_as_cmd); install_element(BGP_NODE, &neighbor_remote_as_cmd);
install_element(BGP_NODE, &neighbor_interface_config_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)); memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr)); memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id; api.vrf_id = bgp->vrf_id;
api.nh_vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.safi = safi; api.safi = safi;
api.prefix = *p; 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)); memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr)); memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = peer->bgp->vrf_id; api.vrf_id = peer->bgp->vrf_id;
api.nh_vrf_id = peer->bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.safi = safi; api.safi = safi;
api.prefix = *p; 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 */ /* peer global config reset */
static void peer_global_config_reset(struct peer *peer) static void peer_global_config_reset(struct peer *peer)
{ {
int saved_flags = 0;
int v6only;
peer->change_local_as = 0; peer->change_local_as = 0;
peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1); peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1);
@ -885,13 +884,11 @@ static void peer_global_config_reset(struct peer *peer)
else else
peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
/* This is a per-peer specific flag and so we must preserve it */ /* These are per-peer specific flags and so we must preserve them */
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN);
peer->flags = 0; peer->flags = 0;
SET_FLAG(peer->flags, saved_flags);
if (v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
peer->config = 0; peer->config = 0;
peer->holdtime = 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); 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. */ /* Set up peer's events and timers. */
if (!active && peer_active(peer)) else if (!active && peer_active(peer))
bgp_timer_set(peer); bgp_timer_set(peer);
return peer; return peer;
@ -2340,7 +2340,7 @@ static void peer_group2peer_config_copy(struct peer_group *group,
struct peer *peer) struct peer *peer)
{ {
struct peer *conf; struct peer *conf;
int v6only; int saved_flags = 0;
conf = group->conf; conf = group->conf;
@ -2358,14 +2358,11 @@ static void peer_group2peer_config_copy(struct peer_group *group,
/* GTSM hops */ /* GTSM hops */
peer->gtsm_hops = conf->gtsm_hops; peer->gtsm_hops = conf->gtsm_hops;
/* this flag is per-neighbor and so has to be preserved */ /* These are per-peer specific flags and so we must preserve them */
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN);
/* peer flags apply */
peer->flags = conf->flags; peer->flags = conf->flags;
SET_FLAG(peer->flags, saved_flags);
if (v6only)
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
/* peer config apply */ /* peer config apply */
peer->config = conf->config; 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", vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
bgp->default_subgroup_pkt_queue_max); 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. */ /* BGP client-to-client reflection. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
vty_out(vty, " no bgp client-to-client reflection\n"); vty_out(vty, " no bgp client-to-client reflection\n");
@ -7469,32 +7470,33 @@ static void bgp_pthreads_init()
{ {
frr_pthread_init(); frr_pthread_init();
frr_pthread_new("BGP i/o thread", PTHREAD_IO, bgp_io_start, struct frr_pthread_attr io = {
bgp_io_stop); .id = PTHREAD_IO,
frr_pthread_new("BGP keepalives thread", PTHREAD_KEEPALIVES, .start = frr_pthread_attr_default.start,
bgp_keepalives_start, bgp_keepalives_stop); .stop = frr_pthread_attr_default.stop,
.name = "BGP I/O thread",
/* pre-run initialization */ };
bgp_keepalives_init(); struct frr_pthread_attr ka = {
bgp_io_init(); .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() void bgp_pthreads_run()
{ {
pthread_attr_t attr; struct frr_pthread *io = frr_pthread_get(PTHREAD_IO);
pthread_attr_init(&attr); struct frr_pthread *ka = frr_pthread_get(PTHREAD_KEEPALIVES);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
/* frr_pthread_run(io, NULL);
* Please ensure that the io thread is running frr_pthread_run(ka, NULL);
* 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(PTHREAD_KEEPALIVES, &attr, NULL); /* Wait until threads are ready. */
frr_pthread_wait_running(io);
frr_pthread_wait_running(ka);
} }
void bgp_pthreads_finish() void bgp_pthreads_finish()

View File

@ -390,6 +390,9 @@ struct bgp {
/* Actual coalesce time */ /* Actual coalesce time */
uint32_t coalesce_time; uint32_t coalesce_time;
/* Auto-shutdown new peers */
bool autoshutdown;
u_int32_t addpath_tx_id; u_int32_t addpath_tx_id;
int addpath_tx_used[AFI_MAX][SAFI_MAX]; int addpath_tx_used[AFI_MAX][SAFI_MAX];
@ -916,9 +919,6 @@ struct peer {
/* Send prefix count. */ /* Send prefix count. */
unsigned long scount[AFI_MAX][SAFI_MAX]; unsigned long scount[AFI_MAX][SAFI_MAX];
/* Announcement attribute hash. */
struct hash *hash[AFI_MAX][SAFI_MAX];
/* Notify data. */ /* Notify data. */
struct bgp_notify notify; 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 * 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) { if (red && red->redist_metric_flag) {
attr.med = red->redist_metric; 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_route api;
struct zapi_nexthop *api_nh; struct zapi_nexthop *api_nh;
int i; int i;
struct in_addr **nhp_ary4 = nhp_ary;
struct in6_addr **nhp_ary6 = nhp_ary;
if (!nhp_count) { if (!nhp_count) {
vnc_zlog_debug_verbose("%s: empty nexthop list, skipping", 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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC; api.type = ZEBRA_ROUTE_VNC;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *p; 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); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = MIN(nhp_count, multipath_num); api.nexthop_num = MIN(nhp_count, multipath_num);
for (i = 0; i < api.nexthop_num; i++) { for (i = 0; i < api.nexthop_num; i++) {
struct in_addr *nhp_ary4;
struct in6_addr *nhp_ary6;
api_nh = &api.nexthops[i]; api_nh = &api.nexthops[i];
switch (p->family) { switch (p->family) {
case AF_INET: 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)); sizeof(api_nh->gate.ipv4));
api_nh->type = NEXTHOP_TYPE_IPV4; api_nh->type = NEXTHOP_TYPE_IPV4;
break; break;
case AF_INET6: 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)); sizeof(api_nh->gate.ipv6));
api_nh->type = NEXTHOP_TYPE_IPV6; api_nh->type = NEXTHOP_TYPE_IPV6;
break; 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 Identifier (AFI), namely IPv4 and IPv6. Support is also provided for
multiple sets of per-AFI information via Subsequent Address Family multiple sets of per-AFI information via Subsequent Address Family
Identifiers (SAFI). In addition to unicast information, VPN information 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. @cite{RFC5512} is supported.
@deffn {Command} {show ip bgp vpnv4 all} {} @deffn {Command} {show ip bgp ipv4 vpn} {}
@deffnx {Command} {show ipv6 bgp vpn all} {} @deffnx {Command} {show ipv6 bgp ipv6 vpn} {}
Print active IPV4 or IPV6 routes advertised via the VPN SAFI. Print active IPV4 or IPV6 routes advertised via the VPN SAFI.
@end deffn @end deffn
@deffn {Command} {show ip bgp encap all} {} @deffn {Command} {show bgp ipv4 vpn summary} {}
@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} {}
@deffnx {Command} {show bgp ipv6 vpn summary} {} @deffnx {Command} {show bgp ipv6 vpn summary} {}
Print a summary of neighbor connections for the specified AFI/SAFI combination. Print a summary of neighbor connections for the specified AFI/SAFI combination.
@end deffn @end deffn

View File

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

View File

@ -884,36 +884,37 @@ log file /var/log/zebra.log
! !
interface eth0 interface eth0
ip address 198.168.1.1/24 ip address 198.168.1.1/24
mpls-te on link-params
mpls-te link metric 10 enable
mpls-te link max-bw 1.25e+06 admin-grp 0xa1
mpls-te link max-rsv-bw 1.25e+06 metric 100
mpls-te link unrsv-bw 0 1.25e+06 max-bw 1.25e+07
mpls-te link unrsv-bw 1 1.25e+06 max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06 unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06 unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06 unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06 unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06 unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06 unrsv-bw 5 1.25e+06
mpls-te link rsc-clsclr 0xab unrsv-bw 6 1.25e+06
unrsv-bw 7 1.25e+06
! !
interface eth1 interface eth1
ip address 192.168.2.1/24 ip address 192.168.2.1/24
mpls-te on link-params
mpls-te link metric 10 enable
mpls-te link max-bw 1.25e+06 metric 10
mpls-te link max-rsv-bw 1.25e+06 max-bw 1.25e+07
mpls-te link unrsv-bw 0 1.25e+06 max-rsv-bw 1.25e+06
mpls-te link unrsv-bw 1 1.25e+06 unrsv-bw 0 1.25e+06
mpls-te link unrsv-bw 2 1.25e+06 unrsv-bw 1 1.25e+06
mpls-te link unrsv-bw 3 1.25e+06 unrsv-bw 2 1.25e+06
mpls-te link unrsv-bw 4 1.25e+06 unrsv-bw 3 1.25e+06
mpls-te link unrsv-bw 5 1.25e+06 unrsv-bw 4 1.25e+06
mpls-te link unrsv-bw 6 1.25e+06 unrsv-bw 5 1.25e+06
mpls-te link unrsv-bw 7 1.25e+06 unrsv-bw 6 1.25e+06
mpls-te link rsc-clsclr 0xab unrsv-bw 7 1.25e+06
mpls-te neighbor 192.168.2.2 as 65000 neighbor 192.168.2.2 as 65000
@end group @end group
@end example @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 information between NVAs. BGP based IP VPN support is defined in
@cite{RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs)}, and @cite{RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs)}, and
@cite{RFC4659, BGP-MPLS IP Virtual Private Network (VPN) Extension for @cite{RFC4659, BGP-MPLS IP Virtual Private Network (VPN) Extension for
IPv6 VPN }. Both the Encapsulation Subsequent Address Family Identifier IPv6 VPN }. Encapsulation information is provided via
(SAFI) and the Tunnel Encapsulation Attribute, @cite{RFC5512, The BGP the Tunnel Encapsulation Attribute, @cite{RFC5512, The BGP
Encapsulation Subsequent Address Family Identifier (SAFI) and the BGP Encapsulation Subsequent Address Family Identifier (SAFI) and the BGP
Tunnel Encapsulation Attribute}, are supported. Tunnel Encapsulation Attribute}, are supported.
@ -83,12 +83,10 @@ operating within a VN.
@node General VNC Configuration @node General VNC Configuration
@subsection General VNC Configuration @subsection General VNC Configuration
@deffn {VNC} {vnc advertise-un-method encap-safi|encap-attr} {} @deffn {VNC} {vnc advertise-un-method encap-attr} {}
Advertise NVE underlay-network IP addresses using the encapsulation SAFI Advertise NVE underlay-network IP addresses using
(@code{encap-safi}) or the UN address sub-TLV of the Tunnel Encapsulation attribute the UN address sub-TLV of the Tunnel Encapsulation attribute
(@code{encap-attr}). When @code{encap-safi} is used, neighbors under (@code{encap-attr}). The default is @code{encap-attr}.
@code{address-family encap} and/or @code{address-family encapv6} must be
configured. The default is @code{encap-attr}.
@end deffn @end deffn
@node RFP Related Configuration @node RFP Related Configuration
@ -356,8 +354,7 @@ by receiving NVAs.
The second form, @code{rt import} specifies an @var{import rt-list}, The second form, @code{rt import} specifies an @var{import rt-list},
which is a filter for incoming routes. which is a filter for incoming routes.
In order to be made available to NVEs in the group, In order to be made available to NVEs in the group,
incoming BGP VPN and @w{ENCAP} @w{SAFI} (when @code{vnc incoming BGP VPN @w{SAFI} routes must have
advertise-un-method encap-safi} is set) routes must have
RT lists that have at least one route target in common with the RT lists that have at least one route target in common with the
group's @var{import rt-list}. 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.101 remote-as 64512
neighbor 192.168.1.102 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.101 activate
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
exit-address-family exit-address-family
@ -1043,7 +1040,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
neighbor 192.168.1.102 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.100 activate
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
exit-address-family exit-address-family
@ -1066,7 +1063,7 @@ router bgp 64512
neighbor 192.168.1.101 remote-as 64512 neighbor 192.168.1.101 remote-as 64512
neighbor 192.168.1.102 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.100 activate
neighbor 192.168.1.101 activate neighbor 192.168.1.101 activate
exit-address-family exit-address-family
@ -1131,7 +1128,7 @@ router bgp 64512
neighbor 172.16.2.2 route-reflector-client neighbor 172.16.2.2 route-reflector-client
exit-address-family exit-address-family
! !
address-family vpnv4 unicast address-family ipv4 vpn
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
neighbor 192.168.1.103 activate neighbor 192.168.1.103 activate
neighbor 192.168.1.104 activate neighbor 192.168.1.104 activate
@ -1161,7 +1158,7 @@ router bgp 64512
no neighbor 192.168.1.103 activate no neighbor 192.168.1.103 activate
exit-address-family exit-address-family
! !
address-family vpnv4 unicast address-family ipv4 vpn
neighbor 192.168.1.101 activate neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
neighbor 192.168.1.103 activate neighbor 192.168.1.103 activate
@ -1250,7 +1247,7 @@ router bgp 64512
neighbor 192.168.1.102 route-reflector-client neighbor 192.168.1.102 route-reflector-client
exit-address-family exit-address-family
address-family vpnv4 address-family ipv4 vpn
neighbor 192.168.1.101 activate neighbor 192.168.1.101 activate
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
@ -1269,7 +1266,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
address-family vpnv4 address-family ipv4 vpn
neighbor 192.168.1.100 activate neighbor 192.168.1.100 activate
exit-address-family exit-address-family
@ -1290,7 +1287,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
address-family vpnv4 address-family ipv4 vpn
neighbor 192.168.1.100 activate neighbor 192.168.1.100 activate
exit-address-family exit-address-family
@ -1381,7 +1378,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
address-family vpnv4 address-family ipv4 vpn
neighbor 192.168.1.100 activate neighbor 192.168.1.100 activate
exit-address-family exit-address-family
@ -1402,7 +1399,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
address-family vpnv4 address-family ipv4 vpn
neighbor 192.168.1.100 activate neighbor 192.168.1.100 activate
exit-address-family 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 description iBGP-client-192-168-1-102
neighbor 192.168.1.102 route-reflector-client 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.101 activate
neighbor 192.168.1.102 activate neighbor 192.168.1.102 activate
neighbor 192.168.1.104 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.100 remote-as 64512
neighbor 192.168.1.104 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.100 activate
neighbor 192.168.1.104 activate neighbor 192.168.1.104 activate
exit-address-family exit-address-family
@ -1493,7 +1490,7 @@ router bgp 64512
neighbor 192.168.1.100 remote-as 64512 neighbor 192.168.1.100 remote-as 64512
neighbor 192.168.1.104 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.100 activate
neighbor 192.168.1.104 activate neighbor 192.168.1.104 activate
exit-address-family 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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP; api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p)); memcpy(&api.prefix, p, sizeof(*p));
@ -407,6 +408,7 @@ void eigrp_zebra_route_delete(struct prefix *p)
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP; api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p)); 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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *prefix; api.prefix = *prefix;
@ -329,6 +330,7 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS; api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *prefix; 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 * Copyright (C) 2017 Cumulus Networks
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -25,78 +25,99 @@
#include "memory.h" #include "memory.h"
#include "hash.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; static unsigned int next_id = 0;
/* Hash table of all frr_pthreads along with synchronization primitive(s) and /* default frr_pthread start/stop routine prototypes */
* hash table callbacks. static void *fpt_run(void *arg);
* ------------------------------------------------------------------------ */ static int fpt_halt(struct frr_pthread *fpt, void **res);
static struct hash *pthread_table;
static pthread_mutex_t pthread_table_mtx = PTHREAD_MUTEX_INITIALIZER;
/* pthread_table->hash_cmp */ /* default frr_pthread attributes */
static int pthread_table_hash_cmp(const void *value1, const void *value2) 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 *tq1 = value1;
const struct frr_pthread *tq2 = value2; const struct frr_pthread *tq2 = value2;
return (tq1->id == tq2->id); return (tq1->attr.id == tq2->attr.id);
} }
/* pthread_table->hash_key */ /* frr_pthread_hash->hash_key */
static unsigned int pthread_table_hash_key(void *value) 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() 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, frr_pthread_hash = hash_create(frr_pthread_hash_key,
pthread_table_hash_cmp, NULL); frr_pthread_hash_cmp, NULL);
} }
pthread_mutex_unlock(&pthread_table_mtx); pthread_mutex_unlock(&frr_pthread_hash_mtx);
} }
void frr_pthread_finish() 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); (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, struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr)
void *(*start_routine)(void *),
int (*stop_routine)(void **,
struct frr_pthread *))
{ {
static struct frr_pthread holder = {0}; static struct frr_pthread holder = {0};
struct frr_pthread *fpt = NULL; 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)) { if (!hash_lookup(frr_pthread_hash, &holder)) {
struct frr_pthread *fpt = XCALLOC( fpt = XCALLOC(MTYPE_FRR_PTHREAD,
MTYPE_FRR_PTHREAD, sizeof(struct frr_pthread)); sizeof(struct frr_pthread));
fpt->id = id; /* create new thread master */
fpt->master = thread_master_create(name); fpt->master = thread_master_create(attr->name);
fpt->start_routine = start_routine; /* set attributes */
fpt->stop_routine = stop_routine; fpt->attr = *attr;
fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); 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; 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) void frr_pthread_destroy(struct frr_pthread *fpt)
{ {
thread_master_free(fpt->master); 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); XFREE(MTYPE_FRR_PTHREAD, fpt);
} }
@ -113,74 +138,82 @@ struct frr_pthread *frr_pthread_get(unsigned int id)
static struct frr_pthread holder = {0}; static struct frr_pthread holder = {0};
struct frr_pthread *fpt; struct frr_pthread *fpt;
pthread_mutex_lock(&pthread_table_mtx); pthread_mutex_lock(&frr_pthread_hash_mtx);
{ {
holder.id = id; holder.attr.id = id;
fpt = hash_lookup(pthread_table, &holder); fpt = hash_lookup(frr_pthread_hash, &holder);
} }
pthread_mutex_unlock(&pthread_table_mtx); pthread_mutex_unlock(&frr_pthread_hash_mtx);
return fpt; 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; int ret;
if (!fpt) ret = pthread_create(&fpt->thread, attr, fpt->attr.start, fpt);
return -1;
ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg); /*
* Per pthread_create(3), the contents of fpt->thread are undefined if
/* Per pthread_create(3), the contents of fpt->thread are undefined if * pthread_create() did not succeed. Reset this value to zero.
* pthread_create() did not succeed. Reset this value to zero. */ */
if (ret < 0) if (ret < 0)
memset(&fpt->thread, 0x00, sizeof(fpt->thread)); memset(&fpt->thread, 0x00, sizeof(fpt->thread));
return ret; return ret;
} }
/** void frr_pthread_wait_running(struct frr_pthread *fpt)
* 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)
{ {
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)); memset(&fpt->thread, 0x00, sizeof(fpt->thread));
return ret; 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. * Callback for hash_iterate to stop all frr_pthread's.
*/ */
static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg) static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg)
{ {
struct frr_pthread *fpt = hb->data; struct frr_pthread *fpt = hb->data;
frr_pthread_stop_actual(fpt, NULL); frr_pthread_stop(fpt, NULL);
} }
void frr_pthread_stop_all() 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() unsigned int frr_pthread_get_id()
{ {
/* just a sanity check, this should never happen */
assert(next_id <= INT_MAX - 1);
return next_id++; return next_id++;
} }
@ -188,3 +221,60 @@ void frr_pthread_yield(void)
{ {
(void)sched_yield(); (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 * Copyright (C) 2017 Cumulus Networks
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -21,36 +21,73 @@
#define _FRR_PTHREAD_H #define _FRR_PTHREAD_H
#include <pthread.h> #include <pthread.h>
#include "frratomic.h"
#include "memory.h"
#include "thread.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 { struct frr_pthread {
/* pthread id */ /* pthread id */
pthread_t thread; pthread_t thread;
/* frr thread identifier */
unsigned int id;
/* thread master for this pthread's thread.c event loop */ /* thread master for this pthread's thread.c event loop */
struct thread_master *master; struct thread_master *master;
/* start routine */ /* caller-specified data; start & stop funcs, name, id */
void *(*start_routine)(void *); 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. * Must be called before using any of the other functions.
*/ */
void frr_pthread_init(void); void frr_pthread_init(void);
/* Uninitializes this module. /*
* Uninitializes this module.
* *
* Destroys all registered frr_pthread's and internal data structures. * Destroys all registered frr_pthread's and internal data structures.
* *
@ -59,34 +96,23 @@ void frr_pthread_init(void);
*/ */
void frr_pthread_finish(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 * The 'attr' argument should be filled out with the desired attributes,
* return value will be NULL. * 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
* @param name - the name of the thread. Doesn't have to be unique, but it * set up to run a basic threadmaster loop and the name will be "Anonymous".
* probably should be. This value is copied and may be safely free'd upon * Scheduling tasks onto the threadmaster in the 'master' field of the returned
* return. * frr_pthread will cause them to run on that pthread.
*
* @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.
* *
* @param attr - the thread attributes
* @return the created frr_pthread upon success, or NULL upon failure * @return the created frr_pthread upon success, or NULL upon failure
*/ */
struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr);
void *(*start_routine)(void *),
int (*stop_routine)(void **,
struct frr_pthread *));
/* Destroys an frr_pthread. /*
* Destroys an frr_pthread.
* *
* Assumes that the associated pthread, if any, has already terminated. * 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); 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 * @return frr_thread associated with the provided id, or NULL on error
*/ */
struct frr_pthread *frr_pthread_get(unsigned int id); 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 * 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 * 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 * 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 * 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 * 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(). * 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 attr - see pthread_create(3)
* @param arg - see pthread_create(3)
* *
* @return 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 * @param result - where to store the thread's result, if any. May be NULL if a
* result is not needed. * 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. */ /* Stops all frr_pthread's. */
void frr_pthread_stop_all(void); void frr_pthread_stop_all(void);
@ -133,7 +187,8 @@ void frr_pthread_stop_all(void);
/* Yields the current thread of execution */ /* Yields the current thread of execution */
void frr_pthread_yield(void); 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 * Internally, this is an integer that increments after each call to this
* function. Because the number of pthreads created should never exceed INT_MAX * 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_link_params_free(ifp);
if (ifp->desc)
XFREE(MTYPE_TMP, ifp->desc);
XFREE(MTYPE_IF, ifp); 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 vrf *vrf;
struct interface if_tmp; 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); vrf = vrf_lookup_by_id(vrf_id);
if (!vrf) if (!vrf)
return NULL; return NULL;

View File

@ -452,6 +452,13 @@ struct nbr_connected {
/* Prototypes. */ /* Prototypes. */
extern int if_cmp_name_func(char *, char *); 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 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_create(const char *name, vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index(ifindex_t, 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). */ /* MPLS label value as a 32-bit (mostly we only care about the label value). */
typedef unsigned int mpls_label_t; 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 /* 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 * 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 * 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) 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; nhl1 = nh1->nh_label;
nhl2 = nh2->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, void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t type,
u_int8_t num_labels, mpls_label_t *label) u_int8_t num_labels, mpls_label_t *label)
{ {
struct nexthop_label *nh_label; struct mpls_label_stack *nh_label;
int i; int i;
nexthop->nh_label_type = type; nexthop->nh_label_type = type;
nh_label = XCALLOC(MTYPE_NH_LABEL, nh_label = XCALLOC(MTYPE_NH_LABEL,
sizeof(struct nexthop_label) sizeof(struct mpls_label_stack)
+ num_labels * sizeof(mpls_label_t)); + num_labels * sizeof(mpls_label_t));
nh_label->num_labels = num_labels; nh_label->num_labels = num_labels;
for (i = 0; i < num_labels; i++) 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) == NEXTHOP_TYPE_IFINDEX || (type) == NEXTHOP_TYPE_BLACKHOLE) \
? (type) : ((type) | 1) ? (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. */ /* Nexthop structure. */
struct nexthop { struct nexthop {
struct nexthop *next; struct nexthop *next;
@ -107,7 +100,7 @@ struct nexthop {
enum lsp_types_t nh_label_type; enum lsp_types_t nh_label_type;
/* Label(s) associated with this nexthop. */ /* 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 /* The following for loop allows to iterate over the nexthop

View File

@ -25,10 +25,11 @@
#include "openbsd-tree.h" #include "openbsd-tree.h"
#include "linklist.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_DEFAULT 0
#define NS_UNKNOWN UINT32_MAX
/* Default netns directory (Linux) */ /* Default netns directory (Linux) */
#define NS_RUN_DIR "/var/run/netns" #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) 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 */ /* Cancel POLLHUP too just in case some bozo set it */
state |= POLLHUP; state |= POLLHUP;
@ -926,8 +928,18 @@ static void thread_cancel_rw(struct thread_master *master, int fd, short state)
nfds_t i; nfds_t i;
for (i = 0; i < master->handler.pfdcount; 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; 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. */ /* NOT out event. */
master->handler.pfds[i].events &= ~(state); 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; int new = 0;
if (debug_vrf) 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 */ /* Nothing to see, move along here */
if (!name && vrf_id == VRF_UNKNOWN) if (!name && vrf_id == VRF_UNKNOWN)
@ -267,8 +267,8 @@ void *vrf_info_lookup(vrf_id_t vrf_id)
* VRF bit-map * VRF bit-map
*/ */
#define VRF_BITMAP_NUM_OF_GROUPS 8 #define VRF_BITMAP_NUM_OF_GROUPS 1024
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS) #define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \ #define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
(VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ (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; struct vrf *vrf = NULL;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { 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)); vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
} }
} }

View File

@ -32,8 +32,7 @@
/* The default VRF ID */ /* The default VRF ID */
#define VRF_DEFAULT 0 #define VRF_DEFAULT 0
#define VRF_UNKNOWN UINT16_MAX #define VRF_UNKNOWN UINT32_MAX
#define VRF_ALL UINT16_MAX - 1
/* Pending: May need to refine this. */ /* Pending: May need to refine this. */
#ifndef IFLA_VRF_MAX #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_putw(s, ZEBRA_HEADER_SIZE);
stream_putc(s, ZEBRA_HEADER_MARKER); stream_putc(s, ZEBRA_HEADER_MARKER);
stream_putc(s, ZSERV_VERSION); stream_putc(s, ZSERV_VERSION);
stream_putw(s, vrf_id); stream_putl(s, vrf_id);
stream_putw(s, command); 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; *size -= ZEBRA_HEADER_SIZE;
STREAM_GETC(s, *marker); STREAM_GETC(s, *marker);
STREAM_GETC(s, *version); STREAM_GETC(s, *version);
STREAM_GETW(s, *vrf_id); STREAM_GETL(s, *vrf_id);
STREAM_GETW(s, *cmd); STREAM_GETW(s, *cmd);
if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) { if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) {
@ -389,25 +389,28 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
vrf_id); vrf_id);
/* Flush all redistribute request. */ /* Flush all redistribute request. */
if (vrf_id == VRF_DEFAULT) if (vrf_id == VRF_DEFAULT) {
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (zclient->mi_redist[afi][i].enabled) { if (!zclient->mi_redist[afi][i].enabled)
struct listnode *node; continue;
u_short *id;
for (ALL_LIST_ELEMENTS_RO( struct listnode *node;
zclient->mi_redist[afi][i] u_short *id;
.instances,
node, id)) for (ALL_LIST_ELEMENTS_RO(
if (!(i == zclient->redist_default zclient->mi_redist[afi][i]
&& *id == zclient->instance)) .instances, node, id))
zebra_redistribute_send( if (!(i == zclient->redist_default
ZEBRA_REDISTRIBUTE_ADD, && *id == zclient->instance))
zclient, afi, i, zebra_redistribute_send(
*id, ZEBRA_REDISTRIBUTE_ADD,
VRF_DEFAULT); zclient, afi, i,
} *id,
VRF_DEFAULT);
}
}
}
/* Flush all redistribute request. */ /* Flush all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
@ -447,29 +450,32 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
/* Set unwanted redistribute route. */ /* Set unwanted redistribute route. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) 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); vrf_id);
/* Flush all redistribute request. */ /* Flush all redistribute request. */
if (vrf_id == VRF_DEFAULT) if (vrf_id == VRF_DEFAULT) {
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (zclient->mi_redist[afi][i].enabled) { if (!zclient->mi_redist[afi][i].enabled)
struct listnode *node; continue;
u_short *id;
for (ALL_LIST_ELEMENTS_RO( struct listnode *node;
zclient->mi_redist[afi][i] u_short *id;
.instances,
node, id)) for (ALL_LIST_ELEMENTS_RO(
if (!(i == zclient->redist_default zclient->mi_redist[afi][i]
&& *id == zclient->instance)) .instances, node, id))
zebra_redistribute_send( if (!(i == zclient->redist_default
ZEBRA_REDISTRIBUTE_DELETE, && *id == zclient->instance))
zclient, afi, i, zebra_redistribute_send(
*id, ZEBRA_REDISTRIBUTE_DELETE,
VRF_DEFAULT); zclient, afi, i,
} *id,
VRF_DEFAULT);
}
}
}
/* Flush all redistribute request. */ /* Flush all redistribute request. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
@ -608,6 +614,33 @@ static int zclient_connect(struct thread *t)
return zclient_start(zclient); 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 * "xdr_encode"-like interface that allows daemon (client) to send
* a message to zebra server for a route that needs to be * a message to zebra server for a route that needs to be
@ -942,6 +975,8 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
} }
stream_putw(s, api->nexthop_num); 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++) { for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i]; api_nh = &api->nexthops[i];
@ -1091,6 +1126,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
return -1; return -1;
} }
if (api->nexthop_num)
STREAM_GETW(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) { for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i]; api_nh = &api->nexthops[i];
@ -1677,7 +1715,7 @@ struct interface *zebra_interface_vrf_update_read(struct stream *s,
{ {
unsigned int ifindex; unsigned int ifindex;
struct interface *ifp; struct interface *ifp;
vrf_id_t new_id = VRF_DEFAULT; vrf_id_t new_id;
/* Get interface index. */ /* Get interface index. */
ifindex = stream_getl(s); ifindex = stream_getl(s);
@ -2043,7 +2081,7 @@ static int zclient_read(struct thread *thread)
length = stream_getw(zclient->ibuf); length = stream_getw(zclient->ibuf);
marker = stream_getc(zclient->ibuf); marker = stream_getc(zclient->ibuf);
version = 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); command = stream_getw(zclient->ibuf);
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { 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); 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_putl(s, master->ifindex);
stream_putw(s, slave->vrf_id); stream_putl(s, slave->vrf_id);
stream_putl(s, slave->ifindex); stream_putl(s, slave->ifindex);
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));

View File

@ -40,7 +40,7 @@
#define ZEBRA_MAX_PACKET_SIZ 4096 #define ZEBRA_MAX_PACKET_SIZ 4096
/* Zebra header size. */ /* Zebra header size. */
#define ZEBRA_HEADER_SIZE 8 #define ZEBRA_HEADER_SIZE 10
/* special socket path name to use TCP /* special socket path name to use TCP
* @ is used as first character because that's abstract socket names on Linux * @ 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. * always set to 255 in new zserv.
*/ */
uint8_t version; uint8_t version;
#define ZSERV_VERSION 4 #define ZSERV_VERSION 5
vrf_id_t vrf_id; vrf_id_t vrf_id;
uint16_t command; uint16_t command;
}; };
@ -281,6 +281,7 @@ struct zapi_route {
u_int32_t mtu; u_int32_t mtu;
vrf_id_t vrf_id; vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
struct ethaddr rmac; struct ethaddr rmac;
}; };
@ -420,6 +421,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t *new_vrf_id); vrf_id_t *new_vrf_id);
extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
#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 *, extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated)); struct zapi_ipv4 *) __attribute__((deprecated));
@ -478,6 +484,9 @@ extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *,
struct zapi_ipv6 *) struct zapi_ipv6 *)
__attribute__((deprecated)); __attribute__((deprecated));
extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *); 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_encode(u_char, struct stream *, struct zapi_route *);
extern int zapi_route_decode(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, 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; typedef u_int16_t zebra_command_t;
/* VRF ID type. */ /* VRF ID type. */
typedef u_int16_t vrf_id_t; typedef uint32_t vrf_id_t;
typedef uint32_t route_tag_t; typedef uint32_t route_tag_t;
#define ROUTE_TAG_MAX UINT32_MAX #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)); memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_NHRP; api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = *p; api.prefix = *p;
switch (type) { 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); ospf6_route_copy_nexthops(route, abr_entry);
/* (7) If the routes are identical, copy the next hops over to existing /* (7) If the routes are identical, copy the next hops over to existing
route. ospf6's route table implementation will otherwise string both route. ospf6's route table implementation will otherwise string both
routes, but keep the older one as the best route since the routes 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)) { if (old && (ospf6_route_cmp(route, old) == 0)) {
ospf6_route_merge_nexthops(old, route); 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 */ /* Update RIB/FIB */
if (table->hook_add) if (table->hook_add)
(*table->hook_add)(old); (*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); ospf6_route_delete(route);
} else { } else {
if (is_debug) 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_ia_add_nw_route (table, &prefix, route); */
ospf6_route_add(route, table); 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) 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); 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_add = ospf6_area_lsdb_hook_add;
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove; oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
oa->lsdb_self = ospf6_lsdb_create(oa); 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 = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
oa->spf_table->scope = oa; 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);
ospf6_lsdb_delete(oa->lsdb_self); ospf6_lsdb_delete(oa->lsdb_self);
ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
ospf6_spf_table_finish(oa->spf_table); ospf6_spf_table_finish(oa->spf_table);
ospf6_route_table_delete(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;
struct ospf6_lsdb *lsdb_self; struct ospf6_lsdb *lsdb_self;
struct ospf6_lsdb *temp_router_lsa_lsdb;
struct ospf6_route_table *spf_table; struct ospf6_route_table *spf_table;
struct ospf6_route_table *route_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); 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) void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
{ {
struct ospf6_as_external_lsa *external; struct ospf6_as_external_lsa *external;
struct prefix asbr_id; 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]; char buf[PREFIX2STR_BUFFER];
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( 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); 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)) { if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf, sizeof(buf)); 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);
} }
ospf6_route_add(route, ospf6->route_table);
} }
void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) 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); nroute = ospf6_route_next(route);
if (route->type != OSPF6_DEST_TYPE_NETWORK) if (route->type != OSPF6_DEST_TYPE_NETWORK)
continue; continue;
if (route->path.origin.type != lsa->header->type)
continue; /* Route has multiple ECMP paths remove,
if (route->path.origin.id != lsa->header->id) * matching path and update effective route's nh list.
continue; */
if (route->path.origin.adv_router != lsa->header->adv_router) 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; 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)
continue;
}
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
prefix2str(&route->prefix, buf, sizeof(buf)); 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); 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 int config_write_ospf6_debug_asbr(struct vty *vty);
extern void install_element_ospf6_debug_asbr(void); 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 */ #endif /* OSPF6_ASBR_H */

View File

@ -1008,6 +1008,103 @@ DEFUN (show_ipv6_ospf6_interface,
return CMD_SUCCESS; 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, DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
show_ipv6_ospf6_interface_ifname_prefix_cmd, show_ipv6_ospf6_interface_ifname_prefix_cmd,
"show ipv6 ospf6 interface IFNAME prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]", "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_cmd);
install_element(VIEW_NODE, install_element(VIEW_NODE,
&show_ipv6_ospf6_interface_ifname_prefix_cmd); &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, &ipv6_ospf6_cost_cmd);
install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);

View File

@ -117,6 +117,19 @@ struct ospf6_interface {
/* BFD information */ /* BFD information */
void *bfd_info; 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 QOBJ_FIELDS
}; };
DECLARE_QOBJ_TYPE(ospf6_interface) 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)) { if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
prefix2str(&route->prefix, buf, sizeof(buf)); 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); 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 */ /* ospf6 age functions */
/* calculate birth */ /* calculate birth */
static void ospf6_lsa_age_set(struct ospf6_lsa *lsa) void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
{ {
struct timeval now; 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 int config_write_ospf6_debug_lsa(struct vty *vty);
extern void install_element_ospf6_debug_lsa(void); extern void install_element_ospf6_debug_lsa(void);
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
#endif /* OSPF6_LSA_H */ #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_SPFTREE, "OSPF6 SPF tree")
DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop") DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop")
DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO, "OSPF6 ext. info") DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO, "OSPF6 ext. info")
DEFINE_MTYPE(OSPF6D, OSPF6_PATH, "OSPF6 Path")
DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other") DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other")

View File

@ -40,6 +40,7 @@ DECLARE_MTYPE(OSPF6_VERTEX)
DECLARE_MTYPE(OSPF6_SPFTREE) DECLARE_MTYPE(OSPF6_SPFTREE)
DECLARE_MTYPE(OSPF6_NEXTHOP) DECLARE_MTYPE(OSPF6_NEXTHOP)
DECLARE_MTYPE(OSPF6_EXTERNAL_INFO) DECLARE_MTYPE(OSPF6_EXTERNAL_INFO)
DECLARE_MTYPE(OSPF6_PATH)
DECLARE_MTYPE(OSPF6_OTHER) DECLARE_MTYPE(OSPF6_OTHER)
#endif /* _QUAGGA_OSPF6_MEMORY_H */ #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++; backupseen++;
} }
oi->hello_in++;
/* Execute neighbor events */ /* Execute neighbor events */
thread_execute(master, hello_received, on, 0); thread_execute(master, hello_received, on, 0);
if (twoway) if (twoway)
@ -776,6 +778,8 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
dbdesc->reserved2 = 0; dbdesc->reserved2 = 0;
} }
oi->db_desc_in++;
if (ntohl(oh->router_id) < ntohl(ospf6->router_id)) if (ntohl(oh->router_id) < ntohl(ospf6->router_id))
ospf6_dbdesc_recv_master(oh, on); ospf6_dbdesc_recv_master(oh, on);
else if (ntohl(ospf6->router_id) < ntohl(oh->router_id)) 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; return;
} }
oi->ls_req_in++;
/* Process each request */ /* Process each request */
for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh); 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 lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh
+ sizeof(struct ospf6_header)); + sizeof(struct ospf6_header));
oi->ls_upd_in++;
/* Process LSAs */ /* Process LSAs */
for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
p < OSPF6_MESSAGE_END(oh) p < OSPF6_MESSAGE_END(oh)
@ -1407,6 +1415,8 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
return; return;
} }
oi->ls_ack_in++;
for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); 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) <= OSPF6_MESSAGE_END(oh);
p += sizeof(struct ospf6_lsa_header)) { p += sizeof(struct ospf6_lsa_header)) {
@ -1777,6 +1787,8 @@ int ospf6_hello_send(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_HELLO; oh->type = OSPF6_MESSAGE_TYPE_HELLO;
oh->length = htons(p - sendbuf); oh->length = htons(p - sendbuf);
oi->hello_out++;
ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh); ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh);
return 0; return 0;
} }
@ -1852,6 +1864,8 @@ int ospf6_dbdesc_send(struct thread *thread)
else else
dst = &on->linklocal_addr; dst = &on->linklocal_addr;
on->ospf6_if->db_desc_out++;
ospf6_send(on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh); ospf6_send(on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
return 0; return 0;
@ -1955,6 +1969,8 @@ int ospf6_lsreq_send(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSREQ; oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
oh->length = htons(p - sendbuf); oh->length = htons(p - sendbuf);
on->ospf6_if->ls_req_out++;
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6, ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6,
on->ospf6_if, oh); on->ospf6_if, oh);
@ -1979,6 +1995,8 @@ static void ospf6_send_lsupdate(struct ospf6_neighbor *on,
{ {
if (on) { if (on) {
on->ospf6_if->ls_upd_out++;
if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) || if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(on->ospf6_if->state == OSPF6_INTERFACE_DR) || (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
(on->ospf6_if->state == OSPF6_INTERFACE_BDR)) { (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); &on->linklocal_addr, on->ospf6_if, oh);
} }
} else if (oi) { } else if (oi) {
oi->ls_upd_out++;
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) || if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
(oi->state == OSPF6_INTERFACE_DR) || (oi->state == OSPF6_INTERFACE_DR) ||
(oi->state == OSPF6_INTERFACE_BDR)) { (oi->state == OSPF6_INTERFACE_BDR)) {
@ -2185,8 +2206,11 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
lsupdate->lsa_number = htonl(lsa_cnt); lsupdate->lsa_number = htonl(lsa_cnt);
ospf6_send_lsupdate(NULL, oi, oh); ospf6_send_lsupdate(NULL, oi, oh);
zlog_debug("%s: LSUpdate length %d", if (IS_OSPF6_DEBUG_MESSAGE(
__PRETTY_FUNCTION__, ntohs(oh->length)); OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
zlog_debug("%s: LSUpdate length %d",
__PRETTY_FUNCTION__,
ntohs(oh->length));
memset(sendbuf, 0, iobuflen); memset(sendbuf, 0, iobuflen);
oh = (struct ospf6_header *)sendbuf; oh = (struct ospf6_header *)sendbuf;
@ -2263,6 +2287,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSACK; oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons(p - sendbuf); oh->length = htons(p - sendbuf);
on->ospf6_if->ls_ack_out++;
ospf6_send(on->ospf6_if->linklocal_addr, ospf6_send(on->ospf6_if->linklocal_addr,
&on->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh); on->ospf6_if, oh);
@ -2288,6 +2314,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
oh->type = OSPF6_MESSAGE_TYPE_LSACK; oh->type = OSPF6_MESSAGE_TYPE_LSACK;
oh->length = htons(p - sendbuf); oh->length = htons(p - sendbuf);
on->ospf6_if->ls_ack_out++;
ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr, ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr,
on->ospf6_if, oh); 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)) { if (ospf6_nexthop_is_set(nh)) {
nh_new = ospf6_nexthop_create(); nh_new = ospf6_nexthop_create();
ospf6_nexthop_copy(nh_new, nh); 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)) { if (!ospf6_route_find_nexthop(dst, nh)) {
nh_new = ospf6_nexthop_create(); nh_new = ospf6_nexthop_create();
ospf6_nexthop_copy(nh_new, nh); 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); 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) if (a->ifindex < b->ifindex)
return -1; return -1;
@ -351,6 +351,36 @@ static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
return 0; 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 *ospf6_route_create(void)
{ {
struct ospf6_route *route; struct ospf6_route *route;
@ -358,6 +388,9 @@ struct ospf6_route *ospf6_route_create(void)
route->nh_list = list_new(); route->nh_list = list_new();
route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp; route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
route->nh_list->del = (void (*) (void *))ospf6_nexthop_delete; 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; return route;
} }
@ -366,6 +399,8 @@ void ospf6_route_delete(struct ospf6_route *route)
if (route) { if (route) {
if (route->nh_list) if (route->nh_list)
list_delete_and_null(&route->nh_list); list_delete_and_null(&route->nh_list);
if (route->paths)
list_delete_and_null(&route->paths);
XFREE(MTYPE_OSPF6_ROUTE, route); 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; for (target = ospf6_route_lookup(&route->prefix, table); target;
target = target->next) { 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 target;
} }
return NULL; 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, vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
route->path.u.cost_e2); 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); vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
/* Nexthops */ /* Nexthops */
vty_out(vty, "Nexthop:\n"); vty_out(vty, "Nexthop:\n");

View File

@ -96,6 +96,9 @@ struct ospf6_path {
u_int32_t cost_config; u_int32_t cost_config;
} u; } u;
u_int32_t tag; u_int32_t tag;
/* nh list for this path */
struct list *nh_list;
}; };
#define OSPF6_PATH_TYPE_NONE 0 #define OSPF6_PATH_TYPE_NONE 0
@ -149,6 +152,9 @@ struct ospf6_route {
/* path */ /* path */
struct ospf6_path path; struct ospf6_path path;
/* List of Paths. */
struct list *paths;
/* nexthop */ /* nexthop */
struct list *nh_list; struct list *nh_list;
}; };
@ -256,6 +262,7 @@ extern void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf,
int size); int size);
extern struct ospf6_nexthop *ospf6_nexthop_create(void); 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_nexthop_delete(struct ospf6_nexthop *nh);
extern void ospf6_clear_nexthops(struct list *nh_list); extern void ospf6_clear_nexthops(struct list *nh_list);
extern int ospf6_num_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 install_element_ospf6_debug_route(void);
extern void ospf6_route_init(void); extern void ospf6_route_init(void);
extern void ospf6_clean(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 */ #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->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
v->nh_list = list_new(); 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->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
v->parent = NULL; 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, static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
struct ospf6_vertex *v, struct ospf6_vertex *v)
uint32_t link_id)
{ {
struct ospf6_lsa *lsa; struct ospf6_lsa *lsa = NULL;
u_int16_t type = 0; u_int16_t type = 0;
u_int32_t id = 0, adv_router = 0; u_int32_t id = 0, adv_router = 0;
if (VERTEX_IS_TYPE(NETWORK, v)) { if (VERTEX_IS_TYPE(NETWORK, v)) {
type = htons(OSPF6_LSTYPE_ROUTER); type = htons(OSPF6_LSTYPE_ROUTER);
id = link_id; id = htonl(0);
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc); adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else { } else {
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) { if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
type = htons(OSPF6_LSTYPE_ROUTER); type = htons(OSPF6_LSTYPE_ROUTER);
id = link_id; id = htonl(0);
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc); adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) { } else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
type = htons(OSPF6_LSTYPE_NETWORK); type = htons(OSPF6_LSTYPE_NETWORK);
@ -185,19 +185,22 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
} }
} }
lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb); 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)) { if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
char ibuf[16], abuf[16]; char ibuf[16], abuf[16];
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf)); inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf)); inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
if (lsa) if (lsa)
zlog_debug(" Link to: %s , V %s id %u", lsa->name, zlog_debug(" Link to: %s len %u, V %s", lsa->name,
v->name, link_id); ntohs(lsa->header->length), v->name);
else 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, ospf6_lstype_name(type), ibuf, abuf,
v->name, link_id); v->name);
} }
return lsa; return lsa;
@ -460,17 +463,14 @@ void ospf6_spf_calculation(u_int32_t router_id,
struct ospf6_vertex *root, *v, *w; struct ospf6_vertex *root, *v, *w;
int size; int size;
caddr_t lsdesc; caddr_t lsdesc;
struct ospf6_lsa *lsa, *self_rtr_lsa = NULL, *rtr_lsa = NULL; struct ospf6_lsa *lsa;
const struct route_node *end = NULL;
struct in6_addr address; struct in6_addr address;
struct ospf6_lsdb *lsdb = NULL;
ospf6_spf_table_finish(result_table); ospf6_spf_table_finish(result_table);
/* Install the calculating router itself as the root of the SPF tree */ /* Install the calculating router itself as the root of the SPF tree */
/* construct root vertex */ /* construct root vertex */
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), router_id, lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
oa->lsdb_self);
if (lsa == NULL) { if (lsa == NULL) {
if (IS_OSPF6_DEBUG_SPF(PROCESS)) if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: No router LSA for area %s\n", __func__, 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; return;
} }
self_rtr_lsa = lsa;
/* initialize */ /* initialize */
candidate_list = pqueue_create(); candidate_list = pqueue_create();
candidate_list->cmp = ospf6_vertex_cmp; candidate_list->cmp = ospf6_vertex_cmp;
@ -509,139 +507,63 @@ void ospf6_spf_calculation(u_int32_t router_id,
&& ospf6_router_is_stub_router(v->lsa))) && ospf6_router_is_stub_router(v->lsa)))
continue; continue;
if (VERTEX_IS_TYPE(ROUTER, v)) { /* For each LS description in the just-added vertex V's LSA */
/* First fetch root Router LSAs from lsdb_self */ size = (VERTEX_IS_TYPE(ROUTER, v)
if (v->lsa == self_rtr_lsa) ? sizeof(struct ospf6_router_lsdesc)
lsdb = oa->lsdb_self; : sizeof(struct ospf6_network_lsdesc));
else for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
lsdb = v->area->lsdb; lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
lsdesc += size) {
lsa = ospf6_lsdesc_lsa(lsdesc, v);
if (lsa == NULL)
continue;
/* Iterating multiple ROUTER LSAs from same adv router if (OSPF6_LSA_IS_MAXAGE(lsa))
* with different Link State ID */ continue;
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)) if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
continue; continue;
if (!ospf6_lsdesc_backlink(lsa, w = ospf6_vertex_create(lsa);
lsdesc, v)) w->area = oa;
continue; w->parent = v;
if (VERTEX_IS_TYPE(ROUTER, v)) {
w = ospf6_vertex_create(lsa); w->cost = v->cost
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)
: sizeof(struct ospf6_network_lsdesc));
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);
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;
if (VERTEX_IS_TYPE(ROUTER, v)) {
w->cost = v->cost
+ ROUTER_LSDESC_GET_METRIC(lsdesc); + ROUTER_LSDESC_GET_METRIC(lsdesc);
w->hops = w->hops =
v->hops v->hops
+ (VERTEX_IS_TYPE(NETWORK, w) ? + (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
0 : 1); } else {
} else /* NETWORK */ { /* NETWORK */
w->cost = v->cost; w->cost = v->cost;
w->hops = v->hops + 1; w->hops = v->hops + 1;
} }
/* nexthop calculation */ /* nexthop calculation */
if (w->hops == 0) if (w->hops == 0)
ospf6_add_nexthop(w->nh_list, ospf6_add_nexthop(
w->nh_list,
ROUTER_LSDESC_GET_IFID(lsdesc), NULL); ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
else if (w->hops == 1 && v->hops == 0) else if (w->hops == 1 && v->hops == 0)
ospf6_nexthop_calc(w, v, lsdesc); ospf6_nexthop_calc(w, v, lsdesc);
else { else
ospf6_copy_nexthops(w->nh_list, ospf6_copy_nexthops(w->nh_list, v->nh_list);
v->nh_list);
}
/* add new candidate to the candidate_list */
if (IS_OSPF6_DEBUG_SPF(PROCESS)) /* add new candidate to the candidate_list */
zlog_debug( if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug(
" New candidate: %s hops %d cost %d", " New candidate: %s hops %d cost %d",
w->name, w->hops, w->cost); w->name, w->hops, w->cost);
pqueue_enqueue(w, candidate_list); pqueue_enqueue(w, candidate_list);
}
} }
} }
pqueue_delete(candidate_list); pqueue_delete(candidate_list);
ospf6_remove_temp_router_lsa(oa);
oa->spf_calculation++; 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, &ospf6_timers_throttle_spf_cmd);
install_element(OSPF6_NODE, &no_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 install_element_ospf6_debug_spf(void);
extern void ospf6_spf_init(void); extern void ospf6_spf_init(void);
extern void ospf6_spf_reason_string(unsigned int reason, char *buf, int size); 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 */ #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) 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_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
ospf6_asbr_lsentry_add(route); ospf6_asbr_lsentry_add(route);
ospf6_abr_originate_summary(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) 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; route->flag |= OSPF6_ROUTE_REMOVE;
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix)); ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
ospf6_asbr_lsentry_remove(route); 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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6; api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *dest; 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)) { if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6; api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *dest; 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)) { if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6; api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = *dest; api.prefix = *dest;

View File

@ -360,6 +360,49 @@ DEFUN (show_ipv6_ospf6_database_router,
return CMD_SUCCESS; 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, DEFUN (show_ipv6_ospf6_database_type_id,
show_ipv6_ospf6_database_type_id_cmd, 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>]", "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( install_element(
VIEW_NODE, VIEW_NODE,
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd); &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. */ /* Make ospf protocol socket. */
ospf6_serv_sock(); 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 router_lsa *rlsa;
struct in_addr *best = NULL; struct in_addr *best = NULL;
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) LSDB_LOOP (ROUTER_LSDB(area), rn, lsa) {
{
/* sanity checks */ /* sanity checks */
if (!lsa || (lsa->data->type != OSPF_ROUTER_LSA) if (!lsa || (lsa->data->type != OSPF_ROUTER_LSA)
|| IS_LSA_SELF(lsa)) || IS_LSA_SELF(lsa))
@ -978,7 +977,7 @@ static void ospf_abr_process_nssa_translates(struct ospf *ospf)
inet_ntoa(area->area_id)); inet_ntoa(area->area_id));
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
ospf_abr_translate_nssa(area, lsa); ospf_abr_translate_nssa(area, lsa);
} }
if (IS_DEBUG_OSPF_NSSA) if (IS_DEBUG_OSPF_NSSA)
@ -1325,14 +1324,14 @@ ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */
and we would want to flush any residuals anyway */ and we would want to flush any residuals anyway */
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) { if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) {
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
if (IS_DEBUG_OSPF_NSSA) if (IS_DEBUG_OSPF_NSSA)
zlog_debug( zlog_debug(
"ospf_abr_unapprove_translates(): " "ospf_abr_unapprove_translates(): "
"approved unset on link id %s", "approved unset on link id %s",
inet_ntoa(lsa->data->id)); inet_ntoa(lsa->data->id));
} }
if (IS_DEBUG_OSPF_NSSA) if (IS_DEBUG_OSPF_NSSA)
zlog_debug("ospf_abr_unapprove_translates(): Stop"); zlog_debug("ospf_abr_unapprove_translates(): Stop");
@ -1355,24 +1354,24 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf)
"considering area %s", "considering area %s",
inet_ntoa(area->area_id)); inet_ntoa(area->area_id));
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa)) { if (ospf_lsa_is_self_originated(ospf, lsa)) {
if (IS_DEBUG_OSPF_EVENT) if (IS_DEBUG_OSPF_EVENT)
zlog_debug( zlog_debug(
"ospf_abr_unapprove_summaries(): " "ospf_abr_unapprove_summaries(): "
"approved unset on summary link id %s", "approved unset on summary link id %s",
inet_ntoa(lsa->data->id)); inet_ntoa(lsa->data->id));
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
} }
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa)) { if (ospf_lsa_is_self_originated(ospf, lsa)) {
if (IS_DEBUG_OSPF_EVENT) if (IS_DEBUG_OSPF_EVENT)
zlog_debug( zlog_debug(
"ospf_abr_unapprove_summaries(): " "ospf_abr_unapprove_summaries(): "
"approved unset on asbr-summary link id %s", "approved unset on asbr-summary link id %s",
inet_ntoa(lsa->data->id)); inet_ntoa(lsa->data->id));
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
} }
} }
if (IS_DEBUG_OSPF_EVENT) if (IS_DEBUG_OSPF_EVENT)
@ -1633,7 +1632,7 @@ static void ospf_abr_remove_unapproved_translates(struct ospf *ospf)
zlog_debug("ospf_abr_remove_unapproved_translates(): Start"); zlog_debug("ospf_abr_remove_unapproved_translates(): Start");
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
ospf_abr_remove_unapproved_translates_apply(ospf, lsa); ospf_abr_remove_unapproved_translates_apply(ospf, lsa);
if (IS_DEBUG_OSPF_NSSA) if (IS_DEBUG_OSPF_NSSA)
zlog_debug("ospf_abr_remove_unapproved_translates(): Stop"); zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
@ -1657,14 +1656,14 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
inet_ntoa(area->area_id)); inet_ntoa(area->area_id));
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa)) if (ospf_lsa_is_self_originated(ospf, lsa))
if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED))
ospf_lsa_flush_area(lsa, area); ospf_lsa_flush_area(lsa, area);
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa)) if (ospf_lsa_is_self_originated(ospf, lsa))
if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED))
ospf_lsa_flush_area(lsa, area); ospf_lsa_flush_area(lsa, area);
} }
if (IS_DEBUG_OSPF_EVENT) if (IS_DEBUG_OSPF_EVENT)

View File

@ -1313,22 +1313,28 @@ int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv,
/* Check msg type. */ /* Check msg type. */
if (mask & Power2[OSPF_ROUTER_LSA]) if (mask & Power2[OSPF_ROUTER_LSA])
LSDB_LOOP(ROUTER_LSDB(area), rn, 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]) if (mask & Power2[OSPF_NETWORK_LSA])
LSDB_LOOP(NETWORK_LSDB(area), rn, 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]) if (mask & Power2[OSPF_SUMMARY_LSA])
LSDB_LOOP(SUMMARY_LSDB(area), rn, 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]) if (mask & Power2[OSPF_ASBR_SUMMARY_LSA])
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, 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]) if (mask & Power2[OSPF_OPAQUE_LINK_LSA])
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, 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]) if (mask & Power2[OSPF_OPAQUE_AREA_LSA])
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, 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 (ospf->lsdb) {
if (mask & Power2[OSPF_AS_EXTERNAL_LSA]) if (mask & Power2[OSPF_AS_EXTERNAL_LSA])
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, 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 */ /* For AS-external opaque LSAs */
if (ospf->lsdb) { if (ospf->lsdb) {
if (mask & Power2[OSPF_OPAQUE_AS_LSA]) if (mask & Power2[OSPF_OPAQUE_AS_LSA])
LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, 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 */ /* 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: case OSPF_OPAQUE_LINK_LSA:
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) 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; break;
case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AREA_LSA:
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) 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; break;
case OSPF_OPAQUE_AS_LSA: case OSPF_OPAQUE_AS_LSA:
LSDB_LOOP(OPAQUE_LINK_LSDB(ospf), rn, 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; break;
default: default:
break; break;

View File

@ -649,7 +649,7 @@ static int ospf_ase_calculate_timer(struct thread *t)
/* Calculate external route for each AS-external-LSA */ /* Calculate external route for each AS-external-LSA */
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
ospf_ase_calculate_route(ospf, lsa); ospf_ase_calculate_route(ospf, lsa);
/* This version simple adds to the table all NSSA areas */ /* This version simple adds to the table all NSSA areas */
if (ospf->anyNSSA) if (ospf->anyNSSA)
@ -661,11 +661,12 @@ static int ospf_ase_calculate_timer(struct thread *t)
if (area->external_routing == OSPF_AREA_NSSA) if (area->external_routing == OSPF_AREA_NSSA)
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) 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 */ /* kevinm: And add the NSSA routes in ospf_top */
LSDB_LOOP(NSSA_LSDB(ospf), rn, lsa) LSDB_LOOP(NSSA_LSDB(ospf), rn, lsa)
ospf_ase_calculate_route(ospf, lsa); ospf_ase_calculate_route(ospf, lsa);
/* Compare old and new external routing table and install the /* Compare old and new external routing table and install the
difference info zebra/kernel */ difference info zebra/kernel */

View File

@ -283,7 +283,7 @@ static void ospf_examine_summaries(struct ospf_area *area,
struct route_node *rn; struct route_node *rn;
LSDB_LOOP(lsdb_rt, rn, lsa) LSDB_LOOP(lsdb_rt, rn, lsa)
process_summary_lsa(area, rt, rtrs, lsa); process_summary_lsa(area, rt, rtrs, lsa);
} }
int ospf_area_is_transit(struct ospf_area *area) int ospf_area_is_transit(struct ospf_area *area)
@ -583,7 +583,7 @@ static void ospf_examine_transit_summaries(struct ospf_area *area,
struct route_node *rn; struct route_node *rn;
LSDB_LOOP(lsdb_rt, rn, lsa) LSDB_LOOP(lsdb_rt, rn, lsa)
process_transit_summary_lsa(area, rt, rtrs, lsa); process_transit_summary_lsa(area, rt, rtrs, lsa);
} }
void ospf_ia_routing(struct ospf *ospf, struct route_table *rt, void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,

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_add, (struct ospf_vl_data * vd), (vd))
DEFINE_HOOK(ospf_vl_delete, (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) int ospf_if_get_output_cost(struct ospf_interface *oi)
{ {
/* If all else fails, use default OSPF cost */ /* 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 struct crypt_key *ospf_crypt_key_new(void);
extern void ospf_crypt_key_add(struct list *, struct crypt_key *); extern void ospf_crypt_key_add(struct list *, struct crypt_key *);
extern int ospf_crypt_key_delete(struct list *, u_char); extern int ospf_crypt_key_delete(struct list *, u_char);
extern u_char ospf_default_iftype(struct interface *ifp); 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 /* Set all multicast memberships appropriately based on the type and
state of the interface. */ 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) if (area->external_routing != OSPF_AREA_NSSA && !type7)
continue; continue;
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) LSDB_LOOP (NSSA_LSDB(area), rn, lsa) {
{
if (lsa->data->id.s_addr if (lsa->data->id.s_addr
== type5->data->id.s_addr) { == type5->data->id.s_addr) {
type7 = lsa; type7 = lsa;
@ -3007,27 +3006,27 @@ int ospf_lsa_maxage_walker(struct thread *thread)
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) LSDB_LOOP(NETWORK_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
} }
/* for AS-external-LSAs. */ /* for AS-external-LSAs. */
if (ospf->lsdb) { if (ospf->lsdb) {
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa)
ospf_lsa_maxage_walker_remover(ospf, lsa); ospf_lsa_maxage_walker_remover(ospf, lsa);
} }
OSPF_TIMER_ON(ospf->t_maxage_walker, ospf_lsa_maxage_walker, OSPF_TIMER_ON(ospf->t_maxage_walker, ospf_lsa_maxage_walker,
@ -3350,20 +3349,20 @@ void ospf_flush_self_originated_lsas_now(struct ospf *ospf)
} }
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
} }
if (need_to_flush_ase) { if (need_to_flush_ase) {
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa)
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
} }
/* /*

View File

@ -280,37 +280,37 @@ static int nsm_negotiation_done(struct ospf_neighbor *nbr)
ospf_proactively_arp(nbr); ospf_proactively_arp(nbr);
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) LSDB_LOOP(NETWORK_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
/* Process only if the neighbor is opaque capable. */ /* Process only if the neighbor is opaque capable. */
if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) {
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
} }
if (CHECK_FLAG(nbr->options, OSPF_OPTION_NP)) { if (CHECK_FLAG(nbr->options, OSPF_OPTION_NP)) {
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
} }
if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
&& area->external_routing == OSPF_AREA_DEFAULT) && area->external_routing == OSPF_AREA_DEFAULT)
LSDB_LOOP(EXTERNAL_LSDB(nbr->oi->ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(nbr->oi->ospf), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
if (CHECK_FLAG(nbr->options, OSPF_OPTION_O) if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)
&& (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK
&& area->external_routing == OSPF_AREA_DEFAULT)) && area->external_routing == OSPF_AREA_DEFAULT))
LSDB_LOOP(OPAQUE_AS_LSDB(nbr->oi->ospf), rn, lsa) LSDB_LOOP(OPAQUE_AS_LSDB(nbr->oi->ospf), rn, lsa)
ospf_db_summary_add(nbr, lsa); ospf_db_summary_add(nbr, lsa);
return 0; return 0;
} }

View File

@ -607,30 +607,6 @@ static void free_opaque_info_per_type(void *val)
ospf_opaque_lsa_flush_schedule(lsa); 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); OSPF_TIMER_OFF(oipt->t_opaque_lsa_self);
list_delete_and_null(&oipt->id_list); list_delete_and_null(&oipt->id_list);
XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt); XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt);

View File

@ -218,7 +218,7 @@ DEFUN_NOSH (router_ospf,
if (ospf->vrf_id != VRF_UNKNOWN) if (ospf->vrf_id != VRF_UNKNOWN)
ospf->oi_running = 1; ospf->oi_running = 1;
if (IS_DEBUG_OSPF_EVENT) 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", instance, ospf->name ? ospf->name : "NIL",
ospf->vrf_id, ospf->oi_running); ospf->vrf_id, ospf->oi_running);
VTY_PUSH_CONTEXT(OSPF_NODE, ospf); 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 interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id); struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
json_object *json_vrf = NULL; json_object *json_vrf = NULL, *json_intf_array = NULL;
json_object *json_interface_sub = NULL; json_object *json_interface_sub = NULL, *json_interface = NULL;
if (use_json) { if (use_json) {
if (use_vrf) if (use_vrf)
json_vrf = json_object_new_object(); json_vrf = json_object_new_object();
else else
json_vrf = json; json_vrf = json;
json_intf_array = json_object_new_array();
} }
if (ospf->instance) { if (ospf->instance) {
@ -3714,21 +3715,29 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (intf_name == NULL) { if (intf_name == NULL) {
if (use_json)
json_object_object_add(json_vrf, "interfaces",
json_intf_array);
/* Show All Interfaces.*/ /* Show All Interfaces.*/
FOR_ALL_INTERFACES (vrf, ifp) { FOR_ALL_INTERFACES (vrf, ifp) {
if (ospf_oi_count(ifp)) { if (ospf_oi_count(ifp)) {
if (use_json) if (use_json) {
json_interface =
json_object_new_object();
json_interface_sub = json_interface_sub =
json_object_new_object(); json_object_new_object();
}
show_ip_ospf_interface_sub(vty, ospf, ifp, show_ip_ospf_interface_sub(vty, ospf, ifp,
json_interface_sub, json_interface_sub,
use_json); use_json);
if (use_json) if (use_json) {
json_object_array_add(json_intf_array,
json_interface);
json_object_object_add( json_object_object_add(
json_vrf, ifp->name, json_interface, ifp->name,
json_interface_sub); json_interface_sub);
}
} }
} }
} else { } else {
@ -3741,15 +3750,23 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf,
else else
vty_out(vty, "No such interface name\n"); vty_out(vty, "No such interface name\n");
} else { } else {
if (use_json) if (use_json) {
json_interface_sub = json_object_new_object(); 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( show_ip_ospf_interface_sub(
vty, ospf, ifp, json_interface_sub, use_json); vty, ospf, ifp, json_interface_sub, use_json);
if (use_json) if (use_json) {
json_object_object_add(json_vrf, ifp->name, json_object_array_add(json_intf_array,
json_interface);
json_object_object_add(json_interface,
ifp->name,
json_interface_sub); json_interface_sub);
}
} }
} }
@ -4283,13 +4300,15 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf,
{ {
struct ospf_interface *oi; struct ospf_interface *oi;
struct listnode *node; 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_json) {
if (use_vrf) if (use_vrf)
json_vrf = json_object_new_object(); json_vrf = json_object_new_object();
else else
json_vrf = json; json_vrf = json;
json_nbr_array = json_object_new_array();
} }
if (ospf->instance) { 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); ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (!use_json) if (!use_json)
show_ip_ospf_neighbour_header(vty); 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)) for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
show_ip_ospf_neighbor_sub(vty, oi, json_vrf, use_json); 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_json) {
if (use_vrf) { 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); 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); ifp = if_lookup_by_name_all_vrf(argv[arg_base]->arg);
if (!ifp) { if (!ifp) {
if (use_json) if (use_json)
@ -6167,7 +6195,7 @@ static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf,
show_database_header[type]); show_database_header[type]);
LSDB_LOOP(AREA_LSDB(area, type), rn, lsa) LSDB_LOOP(AREA_LSDB(area, type), rn, lsa)
show_lsa_summary(vty, lsa, self); show_lsa_summary(vty, lsa, self);
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
@ -6189,7 +6217,7 @@ static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf,
vty_out(vty, "%s\n", show_database_header[type]); vty_out(vty, "%s\n", show_database_header[type]);
LSDB_LOOP(AS_LSDB(ospf, type), rn, lsa) LSDB_LOOP(AS_LSDB(ospf, type), rn, lsa)
show_lsa_summary(vty, lsa, self); show_lsa_summary(vty, lsa, self);
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
@ -8099,7 +8127,7 @@ DEFUN (no_ip_ospf_area,
DEFUN (ospf_redistribute_source, DEFUN (ospf_redistribute_source,
ospf_redistribute_source_cmd, 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 REDIST_STR
FRR_REDIST_HELP_STR_OSPFD FRR_REDIST_HELP_STR_OSPFD
"Metric for redistributed routes\n" "Metric for redistributed routes\n"
@ -8132,13 +8160,15 @@ DEFUN (ospf_redistribute_source,
if (!str2metric(argv[idx]->arg, &metric)) if (!str2metric(argv[idx]->arg, &metric))
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
idx = 1;
/* Get metric type. */ /* 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)) if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
idx = 1;
/* Get route-map */ /* 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); ospf_routemap_set(red, argv[idx]->arg);
} else } else
ospf_routemap_unset(red); ospf_routemap_unset(red);
@ -8148,7 +8178,7 @@ DEFUN (ospf_redistribute_source,
DEFUN (no_ospf_redistribute_source, DEFUN (no_ospf_redistribute_source,
no_ospf_redistribute_source_cmd, 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 NO_STR
REDIST_STR REDIST_STR
FRR_REDIST_HELP_STR_OSPFD FRR_REDIST_HELP_STR_OSPFD
@ -8338,7 +8368,7 @@ DEFUN (no_ospf_distribute_list_out,
/* Default information originate. */ /* Default information originate. */
DEFUN (ospf_default_information_originate, DEFUN (ospf_default_information_originate,
ospf_default_information_originate_cmd, 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" "Control distribution of default information\n"
"Distribute a default route\n" "Distribute a default route\n"
"Always advertise default route\n" "Always advertise default route\n"
@ -8361,18 +8391,21 @@ DEFUN (ospf_default_information_originate,
/* Check whether "always" was specified */ /* Check whether "always" was specified */
if (argv_find(argv, argc, "always", &idx)) if (argv_find(argv, argc, "always", &idx))
default_originate = DEFAULT_ORIGINATE_ALWAYS; default_originate = DEFAULT_ORIGINATE_ALWAYS;
idx = 1;
/* Get metric value */ /* 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)) if (!str2metric(argv[idx]->arg, &metric))
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
idx = 1;
/* Get metric type. */ /* 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)) if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }
idx = 1;
/* Get route-map */ /* 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); ospf_routemap_set(red, argv[idx]->arg);
else else
ospf_routemap_unset(red); ospf_routemap_unset(red);
@ -8383,7 +8416,7 @@ DEFUN (ospf_default_information_originate,
DEFUN (no_ospf_default_information_originate, DEFUN (no_ospf_default_information_originate,
no_ospf_default_information_originate_cmd, 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 NO_STR
"Control distribution of default information\n" "Control distribution of default information\n"
"Distribute a default route\n" "Distribute a default route\n"
@ -9496,9 +9529,9 @@ DEFUN (show_ip_ospf_route,
} }
if (uj) { if (uj) {
/* Keep Non-pretty format */
vty_out(vty, "%s\n", vty_out(vty, "%s\n",
json_object_to_json_string_ext(json, json_object_to_json_string(json));
JSON_C_TO_STRING_PRETTY));
json_object_free(json); json_object_free(json);
} }
@ -9522,9 +9555,9 @@ DEFUN (show_ip_ospf_route,
if (ospf) { if (ospf) {
ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf); ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf);
/* Keep Non-pretty format */
if (uj) if (uj)
vty_out(vty, "%s\n", json_object_to_json_string_ext( vty_out(vty, "%s\n", json_object_to_json_string(json));
json, JSON_C_TO_STRING_PRETTY));
} }
if (uj) if (uj)
@ -9583,7 +9616,7 @@ DEFUN (show_ip_ospf_vrfs,
for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
json_object *json_vrf = NULL; json_object *json_vrf = NULL;
const char *name = NULL; const char *name = NULL;
int vrf_id_ui = 0; int64_t vrf_id_ui = 0;
count++; count++;
@ -9597,7 +9630,8 @@ DEFUN (show_ip_ospf_vrfs,
else else
name = ospf->name; 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) { if (uj) {
json_object_int_add(json_vrf, "vrfId", vrf_id_ui); 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) if (red->dmetric.value >= 0)
vty_out(vty, " metric %d", vty_out(vty, " metric %d",
red->dmetric.value); red->dmetric.value);
if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1)
vty_out(vty, " 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)) if (ROUTEMAP_NAME(red))
vty_out(vty, " route-map %s", 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)); memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id; api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF; api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance; api.instance = ospf->instance;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
@ -466,6 +467,7 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api)); memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id; api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF; api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance; api.instance = ospf->instance;
api.safi = SAFI_UNICAST; 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)); memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id; api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF; api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance; api.instance = ospf->instance;
api.safi = SAFI_UNICAST; 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)); memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id; api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF; api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance; api.instance = ospf->instance;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;

View File

@ -32,6 +32,7 @@
#include "log.h" #include "log.h"
#include "sockunion.h" /* for inet_aton () */ #include "sockunion.h" /* for inet_aton () */
#include "zclient.h" #include "zclient.h"
#include "routemap.h"
#include "plist.h" #include "plist.h"
#include "sockopt.h" #include "sockopt.h"
#include "bfd.h" #include "bfd.h"
@ -159,8 +160,8 @@ void ospf_router_id_update(struct ospf *ospf)
struct ospf_lsa *lsa; struct ospf_lsa *lsa;
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
if (IS_LSA_SELF(lsa)) if (IS_LSA_SELF(lsa))
ospf_lsa_flush_schedule(ospf, lsa); ospf_lsa_flush_schedule(ospf, lsa);
} }
ospf->router_id = router_id; ospf->router_id = router_id;
@ -183,8 +184,7 @@ void ospf_router_id_update(struct ospf *ospf)
struct route_node *rn; struct route_node *rn;
struct ospf_lsa *lsa; 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. */ /* AdvRouter and Router ID is the same. */
if (IPV4_ADDR_SAME(&lsa->data->adv_router, if (IPV4_ADDR_SAME(&lsa->data->adv_router,
&ospf->router_id)) { &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); new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
vrf = vrf_lookup_by_name(new->name); vrf = vrf_lookup_by_name(new->name);
if (IS_DEBUG_OSPF_EVENT) 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); __PRETTY_FUNCTION__, name, new->vrf_id);
if (vrf) if (vrf)
ospf_vrf_link(new, vrf); ospf_vrf_link(new, vrf);
@ -555,6 +555,20 @@ void ospf_terminate(void)
for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
ospf_finish(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 /* Deliberately go back up, hopefully to thread scheduler, as
* One or more ospf_finish()'s may have deferred shutdown to a timer * One or more ospf_finish()'s may have deferred shutdown to a timer
* thread * thread
@ -693,9 +707,9 @@ static void ospf_finish_final(struct ospf *ospf)
stream_free(ospf->ibuf); stream_free(ospf->ibuf);
LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa)
ospf_discard_from_db(ospf, ospf->lsdb, lsa); ospf_discard_from_db(ospf, ospf->lsdb, lsa);
LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
ospf_discard_from_db(ospf, ospf->lsdb, lsa); ospf_discard_from_db(ospf, ospf->lsdb, lsa);
ospf_lsdb_delete_all(ospf->lsdb); ospf_lsdb_delete_all(ospf->lsdb);
ospf_lsdb_free(ospf->lsdb); ospf_lsdb_free(ospf->lsdb);
@ -832,22 +846,21 @@ static void ospf_area_free(struct ospf_area *area)
/* Free LSDBs. */ /* Free LSDBs. */
LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) LSDB_LOOP(NETWORK_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(NSSA_LSDB(area), rn, lsa) LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
ospf_discard_from_db(area->ospf, area->lsdb, lsa); ospf_discard_from_db(area->ospf, area->lsdb, lsa);
ospf_opaque_type10_lsa_term(area);
ospf_lsdb_delete_all(area->lsdb); ospf_lsdb_delete_all(area->lsdb);
ospf_lsdb_free(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) static int ospf_vrf_new(struct vrf *vrf)
{ {
if (IS_DEBUG_OSPF_EVENT) 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); vrf->name, vrf->vrf_id);
return 0; return 0;
@ -2026,7 +2039,7 @@ static int ospf_vrf_new(struct vrf *vrf)
static int ospf_vrf_delete(struct vrf *vrf) static int ospf_vrf_delete(struct vrf *vrf)
{ {
if (IS_DEBUG_OSPF_EVENT) 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); vrf->name, vrf->vrf_id);
return 0; return 0;
@ -2039,7 +2052,7 @@ static int ospf_vrf_enable(struct vrf *vrf)
vrf_id_t old_vrf_id = VRF_DEFAULT; vrf_id_t old_vrf_id = VRF_DEFAULT;
if (IS_DEBUG_OSPF_EVENT) 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); __PRETTY_FUNCTION__, vrf->name, vrf->vrf_id);
ospf = ospf_lookup_by_name(vrf->name); 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". */ /* We have instance configured, link to VRF and make it "up". */
ospf_vrf_link(ospf, vrf); ospf_vrf_link(ospf, vrf);
if (IS_DEBUG_OSPF_EVENT) 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, __PRETTY_FUNCTION__, vrf->name, ospf->vrf_id,
old_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); 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) { if (pim == NULL) {
zlog_err("%s %s: pim class init failure ", __FILE__, zlog_err("%s %s: pim class init failure ", __FILE__,
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);
@ -159,7 +159,7 @@ static int pim_vrf_delete(struct vrf *vrf)
{ {
struct pim_instance *pim = vrf->info; 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_ssmpingd_destroy(pim);
pim_instance_terminate(pim); pim_instance_terminate(pim);

View File

@ -47,40 +47,14 @@
void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient, void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
struct pim_nexthop_cache *pnc, int command) struct pim_nexthop_cache *pnc, int command)
{ {
struct stream *s;
struct prefix *p; struct prefix *p;
int ret; int ret;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return;
p = &(pnc->rpf.rpf_addr); p = &(pnc->rpf.rpf_addr);
s = zclient->obuf; ret = zclient_send_rnh(zclient, command, p, false, pim->vrf_id);
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);
if (ret < 0) if (ret < 0)
zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
if (PIM_DEBUG_PIM_NHT) { if (PIM_DEBUG_PIM_NHT) {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(p, buf, sizeof(buf)); prefix2str(p, buf, sizeof(buf));
@ -811,7 +785,7 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof(buf)); prefix2str(&p, buf, sizeof(buf));
zlog_debug( 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, __PRETTY_FUNCTION__, buf, pim->vrf->name, nexthop_num,
pnc->nexthop_num, vrf_id, pnc->upstream_hash->count, pnc->nexthop_num, vrf_id, pnc->upstream_hash->count,
listcount(pnc->rp_list)); 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) { if (PIM_DEBUG_ZEBRA) {
zlog_debug( 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, __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu, (long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp)); if_is_operative(ifp));
@ -130,7 +130,7 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) { if (PIM_DEBUG_ZEBRA) {
zlog_debug( 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, __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu, (long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp)); if_is_operative(ifp));
@ -158,7 +158,7 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) { if (PIM_DEBUG_ZEBRA) {
zlog_debug( 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, __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu, (long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp)); if_is_operative(ifp));
@ -213,7 +213,7 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) { if (PIM_DEBUG_ZEBRA) {
zlog_debug( 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, __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, vrf_id,
(long)ifp->flags, ifp->metric, ifp->mtu, (long)ifp->flags, ifp->metric, ifp->mtu,
if_is_operative(ifp)); if_is_operative(ifp));
@ -293,7 +293,7 @@ static int pim_zebra_if_address_add(int command, struct zclient *zclient,
if (PIM_DEBUG_ZEBRA) { if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ]; char buf[BUFSIZ];
prefix2str(p, 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, __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) c->flags, CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
? "secondary" ? "secondary"
@ -372,7 +372,7 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
char buf[BUFSIZ]; char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ); prefix2str(p, buf, BUFSIZ);
zlog_debug( 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, __PRETTY_FUNCTION__, c->ifp->name, vrf_id, buf,
c->flags, c->flags,
CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)
@ -765,8 +765,6 @@ void pim_zebra_init(void)
zlog_info("zclient_init cleared redistribution request"); zlog_info("zclient_init cleared redistribution request");
} }
zassert(zclient->redist_default == ZEBRA_ROUTE_PIM);
/* Request all redistribution */ /* Request all redistribution */
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (i == zclient->redist_default) if (i == zclient->redist_default)

View File

@ -22,7 +22,7 @@
%{!?with_multipath: %global with_multipath 256 } %{!?with_multipath: %global with_multipath 256 }
%{!?frr_user: %global frr_user frr } %{!?frr_user: %global frr_user frr }
%{!?vty_group: %global vty_group frrvty } %{!?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_watchfrr: %global with_watchfrr 1 }
%{!?with_bgp_vnc: %global with_bgp_vnc 0 } %{!?with_bgp_vnc: %global with_bgp_vnc 0 }
%{!?with_pimd: %global with_pimd 1 } %{!?with_pimd: %global with_pimd 1 }
@ -554,6 +554,9 @@ rm -rf %{buildroot}
%{_libdir}/lib*.so.0 %{_libdir}/lib*.so.0
%attr(755,root,root) %{_libdir}/lib*.so.0.* %attr(755,root,root) %{_libdir}/lib*.so.0.*
%endif %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 %attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so
%{_bindir}/* %{_bindir}/*
%config(noreplace) /etc/frr/[!v]*.conf* %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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIP; api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST; 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)); memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT; api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIPNG; api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST; api.safi = SAFI_UNICAST;
api.prefix = rp->p; api.prefix = rp->p;

View File

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

View File

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

View File

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

View File

@ -434,7 +434,14 @@ end
new_ctx = False new_ctx = False
log.debug('LINE %-50s: entering new context, %-50s', line, ctx_keys) 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 = [] main_ctx_key = []
# Save old context first # Save old context first

View File

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

View File

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

View File

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

View File

@ -238,10 +238,12 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break; 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); &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); &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) { 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; 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, static int netlink_extract_bridge_info(struct rtattr *link_data,
struct zebra_l2info_bridge *bridge_info) 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), DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp),
(vty, ifp)) (vty, ifp))
static void if_down_del_nbr_connected(struct interface *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, static void zebra_if_node_destroy(route_table_delegate_t *delegate,
struct route_table *table, struct route_table *table,
struct route_node *node) 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); route_table_init_with_delegate(&zebra_if_table_delegate);
ifp->info = zebra_if; 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; return 0;
} }
@ -141,6 +172,8 @@ static int if_zebra_delete_hook(struct interface *ifp)
list_delete_and_null(&rtadv->AdvPrefixList); list_delete_and_null(&rtadv->AdvPrefixList);
#endif /* HAVE_RTADV */ #endif /* HAVE_RTADV */
THREAD_OFF(zebra_if->speed_update);
XFREE(MTYPE_TMP, zebra_if); XFREE(MTYPE_TMP, zebra_if);
} }
@ -735,7 +768,8 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
zebra_interface_vrf_update_add(ifp, old_vrf_id); zebra_interface_vrf_update_add(ifp, old_vrf_id);
/* Install connected routes (in new VRF). */ /* Install connected routes (in new VRF). */
if_install_connected(ifp); if (if_is_operative(ifp))
if_install_connected(ifp);
static_ifindex_update(ifp, true); static_ifindex_update(ifp, true);

View File

@ -273,6 +273,8 @@ struct zebra_if {
/* Link fields - for sub-interfaces. */ /* Link fields - for sub-interfaces. */
ifindex_t link_ifindex; ifindex_t link_ifindex;
struct interface *link; struct interface *link;
struct thread *speed_update;
}; };
DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp), 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 if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE) || 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, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0); &nh, 0, 0, 0, 0, 0);
else else
@ -1096,7 +1096,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE) || 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, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0); &nh, 0, 0, 0, 0, 0);
else else

View File

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

View File

@ -300,6 +300,13 @@ int main(int argc, char **argv)
zebra_if_init(); zebra_if_init();
zebra_debug_init(); zebra_debug_init();
router_id_cmd_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(); access_list_init();
prefix_list_init(); prefix_list_init();
#if defined(HAVE_RTADV) #if defined(HAVE_RTADV)
@ -317,16 +324,6 @@ int main(int argc, char **argv)
/* For debug purpose. */ /* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ /* 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 defined(HANDLE_ZAPI_FUZZING)
if (fuzzing) { if (fuzzing) {
zserv_read_file(fuzzing); zserv_read_file(fuzzing);

View File

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

View File

@ -60,15 +60,17 @@ enum southbound_results {
* semantics so we will end up with a delete than * semantics so we will end up with a delete than
* a re-add. * a re-add.
*/ */
extern void kernel_route_rib(struct prefix *p, struct prefix *src_p, extern void kernel_route_rib(struct route_node *rn, struct prefix *p,
struct route_entry *old, struct route_entry *new); struct prefix *src_p, struct route_entry *old,
struct route_entry *new);
/* /*
* So route install/failure may not be immediately known * So route install/failure may not be immediately known
* so let's separate it out and allow the result to * so let's separate it out and allow the result to
* be passed back up. * 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, struct route_entry *re,
enum southbound_results res); 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 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_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
extern int kernel_add_vtep(vni_t vni, struct interface *ifp, extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip); 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; afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) { if (h->nlmsg_type == RTM_NEWROUTE) {
struct interface *ifp;
vrf_id_t nh_vrf_id = vrf_id;
if (!tb[RTA_MULTIPATH]) { if (!tb[RTA_MULTIPATH]) {
struct nexthop nh; struct nexthop nh;
size_t sz = (afi == AFI_IP) ? 4 : 16; 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) if (gate)
memcpy(&nh.gate, gate, sz); 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, 0, flags, &p, NULL, &nh, table, metric,
mtu, distance, tag); mtu, distance, tag);
} else { } else {
@ -453,6 +463,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
re->metric = metric; re->metric = metric;
re->mtu = mtu; re->mtu = mtu;
re->vrf_id = vrf_id; re->vrf_id = vrf_id;
re->nh_vrf_id = vrf_id;
re->table = table; re->table = table;
re->nexthop_num = 0; re->nexthop_num = 0;
re->uptime = time(NULL); re->uptime = time(NULL);
@ -464,6 +475,18 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
break; break;
index = rtnh->rtnh_ifindex; 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; gate = 0;
if (rtnh->rtnh_len > sizeof(*rtnh)) { if (rtnh->rtnh_len > sizeof(*rtnh)) {
memset(tb, 0, sizeof(tb)); memset(tb, 0, sizeof(tb));
@ -803,7 +826,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
struct rtmsg *rtmsg, struct rtmsg *rtmsg,
size_t req_size, int cmd) 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]; mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256]; 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), routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex); 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); 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 (cmd == RTM_NEWROUTE) {
if (nexthop->rmap_src.ipv4.s_addr) if (nexthop->rmap_src.ipv4.s_addr)
addattr_l(nlmsg, req_size, RTA_PREFSRC, 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) { if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (cmd == RTM_NEWROUTE) { if (cmd == RTM_NEWROUTE) {
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l(nlmsg, req_size, RTA_PREFSRC, 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, struct rtmsg *rtmsg,
union g_addr **src) union g_addr **src)
{ {
struct nexthop_label *nh_label; struct mpls_label_stack *nh_label;
mpls_lse_t out_lse[MPLS_MAX_LABELS]; mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256]; 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), routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex); 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 */ /* ifindex */
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IFINDEX) { || nexthop->type == NEXTHOP_TYPE_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (nexthop->rmap_src.ipv4.s_addr) if (nexthop->rmap_src.ipv4.s_addr)
*src = &nexthop->rmap_src; *src = &nexthop->rmap_src;
else if (nexthop->src.ipv4.s_addr) 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", "nexthop via if %u",
routedesc, nexthop->ifindex); routedesc, nexthop->ifindex);
} else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug( zlog_debug(
"netlink_route_multipath() (%s): " "netlink_route_multipath() (%s): "
@ -1609,8 +1642,9 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
return suc; return suc;
} }
void kernel_route_rib(struct prefix *p, struct prefix *src_p, void kernel_route_rib(struct route_node *rn, struct prefix *p,
struct route_entry *old, struct route_entry *new) struct prefix *src_p, struct route_entry *old,
struct route_entry *new)
{ {
int ret = 0; 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, ret = netlink_route_multipath(RTM_NEWROUTE, p,
src_p, new, 0); src_p, new, 0);
} }
kernel_route_rib_pass_fail(p, new, kernel_route_rib_pass_fail(rn, p, new,
(!ret) ? (!ret) ?
SOUTHBOUND_INSTALL_SUCCESS : SOUTHBOUND_INSTALL_SUCCESS :
SOUTHBOUND_INSTALL_FAILURE); SOUTHBOUND_INSTALL_FAILURE);
@ -1649,7 +1683,7 @@ void kernel_route_rib(struct prefix *p, struct prefix *src_p,
if (old) { if (old) {
ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); 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) ? (!ret) ?
SOUTHBOUND_DELETE_SUCCESS : SOUTHBOUND_DELETE_SUCCESS :
SOUTHBOUND_DELETE_FAILURE); SOUTHBOUND_DELETE_FAILURE);

View File

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

View File

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

View File

@ -713,7 +713,15 @@ static int zfpm_read_cb(struct thread *thread)
nbyte = stream_read_try(ibuf, zfpm_g->sock, nbyte = stream_read_try(ibuf, zfpm_g->sock,
FPM_MSG_HDR_LEN - already); FPM_MSG_HDR_LEN - already);
if (nbyte == 0 || nbyte == -1) { if (nbyte == 0 || nbyte == -1) {
zfpm_connection_down("closed socket in read"); 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; return 0;
} }
@ -743,7 +751,15 @@ static int zfpm_read_cb(struct thread *thread)
nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already); nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already);
if (nbyte == 0 || nbyte == -1) { if (nbyte == 0 || nbyte == -1) {
zfpm_connection_down("failed to read message"); 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; 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); ifindex_t ifindex, mpls_label_t out_label);
static int nhlfe_del(zebra_nhlfe_t *snhlfe); static int nhlfe_del(zebra_nhlfe_t *snhlfe);
static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, 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, static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type); enum lsp_types_t type);
static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, 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; s = client->obuf;
stream_reset(s); 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_putw(s, rn->p.family);
stream_put_prefix(s, &rn->p); stream_put_prefix(s, &rn->p);
@ -1217,7 +1217,7 @@ static int nhlfe_del(zebra_nhlfe_t *nhlfe)
* Update label for NHLFE entry. * Update label for NHLFE entry.
*/ */
static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, 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]; nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
} }

View File

@ -61,7 +61,7 @@ stream_failure:
stream_reset(s); 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.src);
stream_put_in_addr(s, &mroute.sg.grp); stream_put_in_addr(s, &mroute.sg.grp);
stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); stream_put(s, &mroute.lastused, sizeof(mroute.lastused));

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