mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 11:01:48 +00:00
Merge branch 'master' into evpn-symmetric-routing
This commit is contained in:
commit
9bb77a5b3d
@ -133,6 +133,7 @@ dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
|
||||
bgpd.conf.vnc.sample
|
||||
|
||||
bgp_vty.o: bgp_vty_clippy.c
|
||||
bgp_route.o: bgp_route_clippy.c
|
||||
|
||||
EXTRA_DIST = BGP4-MIB.txt
|
||||
|
||||
|
@ -74,6 +74,7 @@ static const struct message attr_str[] = {
|
||||
{BGP_ATTR_AS4_PATH, "AS4_PATH"},
|
||||
{BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
|
||||
{BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"},
|
||||
{BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
|
||||
{BGP_ATTR_ENCAP, "ENCAP"},
|
||||
#if ENABLE_BGP_VNC
|
||||
{BGP_ATTR_VNC, "VNC"},
|
||||
@ -492,19 +493,13 @@ unsigned int attrhash_key_make(void *p)
|
||||
const struct attr *attr = (struct attr *)p;
|
||||
uint32_t key = 0;
|
||||
#define MIX(val) key = jhash_1word(val, key)
|
||||
#define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
|
||||
|
||||
MIX(attr->origin);
|
||||
MIX(attr->nexthop.s_addr);
|
||||
MIX(attr->med);
|
||||
MIX(attr->local_pref);
|
||||
MIX(attr->aggregator_as);
|
||||
MIX(attr->aggregator_addr.s_addr);
|
||||
MIX(attr->weight);
|
||||
MIX(attr->mp_nexthop_global_in.s_addr);
|
||||
MIX(attr->originator_id.s_addr);
|
||||
MIX(attr->tag);
|
||||
MIX(attr->label);
|
||||
MIX(attr->label_index);
|
||||
MIX3(attr->origin, attr->nexthop.s_addr, attr->med);
|
||||
MIX3(attr->local_pref, attr->aggregator_as, attr->aggregator_addr.s_addr);
|
||||
MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr,
|
||||
attr->originator_id.s_addr);
|
||||
MIX3(attr->tag, attr->label, attr->label_index);
|
||||
|
||||
if (attr->aspath)
|
||||
MIX(aspath_key_make(attr->aspath));
|
||||
@ -550,12 +545,6 @@ int attrhash_cmp(const void *p1, const void *p2)
|
||||
&& attr1->tag == attr2->tag
|
||||
&& attr1->label_index == attr2->label_index
|
||||
&& attr1->mp_nexthop_len == attr2->mp_nexthop_len
|
||||
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
|
||||
&attr2->mp_nexthop_global)
|
||||
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
|
||||
&attr2->mp_nexthop_local)
|
||||
&& IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
|
||||
&attr2->mp_nexthop_global_in)
|
||||
&& attr1->ecommunity == attr2->ecommunity
|
||||
&& attr1->lcommunity == attr2->lcommunity
|
||||
&& attr1->cluster == attr2->cluster
|
||||
@ -565,6 +554,12 @@ int attrhash_cmp(const void *p1, const void *p2)
|
||||
#if ENABLE_BGP_VNC
|
||||
&& encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs)
|
||||
#endif
|
||||
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
|
||||
&attr2->mp_nexthop_global)
|
||||
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
|
||||
&attr2->mp_nexthop_local)
|
||||
&& IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
|
||||
&attr2->mp_nexthop_global_in)
|
||||
&& IPV4_ADDR_SAME(&attr1->originator_id,
|
||||
&attr2->originator_id)
|
||||
&& overlay_index_same(attr1, attr2))
|
||||
@ -1040,6 +1035,8 @@ const u_int8_t attr_flags_values[] = {
|
||||
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
||||
[BGP_ATTR_AS4_AGGREGATOR] =
|
||||
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
||||
[BGP_ATTR_PMSI_TUNNEL] =
|
||||
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
||||
[BGP_ATTR_LARGE_COMMUNITIES] =
|
||||
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
|
||||
[BGP_ATTR_PREFIX_SID] =
|
||||
@ -3255,6 +3252,17 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* PMSI Tunnel */
|
||||
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
|
||||
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
|
||||
stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
|
||||
stream_putc(s, 9); // Length
|
||||
stream_putc(s, 0); // Flags
|
||||
stream_putc(s, 6); // Tunnel type: Ingress Replication (6)
|
||||
stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
|
||||
stream_put_ipv4(s, attr->nexthop.s_addr); // Unicast tunnel endpoint IP address
|
||||
}
|
||||
|
||||
/* Unknown transit attribute. */
|
||||
if (attr->transit)
|
||||
stream_put(s, attr->transit->val, attr->transit->length);
|
||||
|
@ -1206,7 +1206,9 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
attr.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
vni2label(vpn->vni, &(attr.label));
|
||||
|
||||
/* Set up RT and ENCAP extended community. */
|
||||
build_evpn_route_extcomm(vpn, &attr,
|
||||
|
@ -574,9 +574,9 @@ static void show_vni_entry(struct hash_backet *backet, void *args[])
|
||||
{
|
||||
struct vty *vty;
|
||||
json_object *json;
|
||||
json_object *json_vni;
|
||||
json_object *json_import_rtl;
|
||||
json_object *json_export_rtl;
|
||||
json_object *json_vni = NULL;
|
||||
json_object *json_import_rtl = NULL;
|
||||
json_object *json_export_rtl = NULL;
|
||||
struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
|
||||
char buf1[10];
|
||||
char buf2[RD_ADDRSTRLEN];
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "thread.h"
|
||||
#include "log.h"
|
||||
#include "stream.h"
|
||||
#include "ringbuf.h"
|
||||
#include "memory.h"
|
||||
#include "plist.h"
|
||||
#include "workqueue.h"
|
||||
@ -155,7 +156,6 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
|
||||
|
||||
stream_fifo_clean(peer->ibuf);
|
||||
stream_fifo_clean(peer->obuf);
|
||||
stream_reset(peer->ibuf_work);
|
||||
|
||||
/*
|
||||
* this should never happen, since bgp_process_packet() is the
|
||||
@ -183,7 +183,9 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
|
||||
stream_fifo_push(peer->ibuf,
|
||||
stream_fifo_pop(from_peer->ibuf));
|
||||
|
||||
stream_copy(peer->ibuf_work, from_peer->ibuf_work);
|
||||
ringbuf_wipe(peer->ibuf_work);
|
||||
ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work,
|
||||
ringbuf_remain(from_peer->ibuf_work));
|
||||
}
|
||||
pthread_mutex_unlock(&from_peer->io_mtx);
|
||||
pthread_mutex_unlock(&peer->io_mtx);
|
||||
@ -264,14 +266,16 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: peer_xfer_stats() must be called with I/O turned OFF
|
||||
if (from_peer)
|
||||
peer_xfer_stats(peer, from_peer);
|
||||
|
||||
bgp_reads_on(peer);
|
||||
bgp_writes_on(peer);
|
||||
thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0,
|
||||
&peer->t_process_packet);
|
||||
|
||||
if (from_peer)
|
||||
peer_xfer_stats(peer, from_peer);
|
||||
|
||||
return (peer);
|
||||
}
|
||||
|
||||
@ -1097,7 +1101,7 @@ int bgp_stop(struct peer *peer)
|
||||
stream_fifo_clean(peer->obuf);
|
||||
|
||||
if (peer->ibuf_work)
|
||||
stream_reset(peer->ibuf_work);
|
||||
ringbuf_wipe(peer->ibuf_work);
|
||||
if (peer->obuf_work)
|
||||
stream_reset(peer->obuf_work);
|
||||
|
||||
|
112
bgpd/bgp_io.c
112
bgpd/bgp_io.c
@ -29,6 +29,7 @@
|
||||
#include "memory.h" // for MTYPE_TMP, XCALLOC, XFREE
|
||||
#include "network.h" // for ERRNO_IO_RETRY
|
||||
#include "stream.h" // for stream_get_endp, stream_getw_from, str...
|
||||
#include "ringbuf.h" // for ringbuf_remain, ringbuf_peek, ringbuf_...
|
||||
#include "thread.h" // for THREAD_OFF, THREAD_ARG, thread, thread...
|
||||
#include "zassert.h" // for assert
|
||||
|
||||
@ -109,13 +110,15 @@ int bgp_io_stop(void **result, struct frr_pthread *fpt)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
while (
|
||||
!atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst))
|
||||
;
|
||||
|
||||
assert(peer->status != Deleted);
|
||||
assert(peer->obuf);
|
||||
assert(peer->ibuf);
|
||||
@ -133,10 +136,6 @@ void bgp_writes_on(struct peer *peer)
|
||||
|
||||
void bgp_writes_off(struct peer *peer)
|
||||
{
|
||||
while (
|
||||
!atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst))
|
||||
;
|
||||
|
||||
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
|
||||
|
||||
thread_cancel_async(fpt->master, &peer->t_write, NULL);
|
||||
@ -147,10 +146,6 @@ void bgp_writes_off(struct peer *peer)
|
||||
|
||||
void bgp_reads_on(struct peer *peer)
|
||||
{
|
||||
while (
|
||||
!atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst))
|
||||
;
|
||||
|
||||
assert(peer->status != Deleted);
|
||||
assert(peer->ibuf);
|
||||
assert(peer->fd);
|
||||
@ -170,10 +165,6 @@ void bgp_reads_on(struct peer *peer)
|
||||
|
||||
void bgp_reads_off(struct peer *peer)
|
||||
{
|
||||
while (
|
||||
!atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst))
|
||||
;
|
||||
|
||||
struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO);
|
||||
|
||||
thread_cancel_async(fpt->master, &peer->t_read, NULL);
|
||||
@ -273,14 +264,12 @@ static int bgp_process_reads(struct thread *thread)
|
||||
/* static buffer for transferring packets */
|
||||
static unsigned char pktbuf[BGP_MAX_PACKET_SIZE];
|
||||
/* shorter alias to peer's input buffer */
|
||||
struct stream *ibw = peer->ibuf_work;
|
||||
/* offset of start of current packet */
|
||||
size_t offset = stream_get_getp(ibw);
|
||||
struct ringbuf *ibw = peer->ibuf_work;
|
||||
/* packet size as given by header */
|
||||
u_int16_t pktsize = 0;
|
||||
uint16_t pktsize = 0;
|
||||
|
||||
/* check that we have enough data for a header */
|
||||
if (STREAM_READABLE(ibw) < BGP_HEADER_SIZE)
|
||||
if (ringbuf_remain(ibw) < BGP_HEADER_SIZE)
|
||||
break;
|
||||
|
||||
/* validate header */
|
||||
@ -292,16 +281,18 @@ static int bgp_process_reads(struct thread *thread)
|
||||
}
|
||||
|
||||
/* header is valid; retrieve packet size */
|
||||
pktsize = stream_getw_from(ibw, offset + BGP_MARKER_SIZE);
|
||||
ringbuf_peek(ibw, BGP_MARKER_SIZE, &pktsize, sizeof(pktsize));
|
||||
|
||||
pktsize = ntohs(pktsize);
|
||||
|
||||
/* if this fails we are seriously screwed */
|
||||
assert(pktsize <= BGP_MAX_PACKET_SIZE);
|
||||
|
||||
/* If we have that much data, chuck it into its own
|
||||
* stream and append to input queue for processing. */
|
||||
if (STREAM_READABLE(ibw) >= pktsize) {
|
||||
if (ringbuf_remain(ibw) >= pktsize) {
|
||||
struct stream *pkt = stream_new(pktsize);
|
||||
stream_get(pktbuf, ibw, pktsize);
|
||||
assert(ringbuf_get(ibw, pktbuf, pktsize) == pktsize);
|
||||
stream_put(pkt, pktbuf, pktsize);
|
||||
|
||||
pthread_mutex_lock(&peer->io_mtx);
|
||||
@ -315,28 +306,12 @@ static int bgp_process_reads(struct thread *thread)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* After reading:
|
||||
* 1. Move unread data to stream start to make room for more.
|
||||
* 2. Reschedule and return when we have additional data.
|
||||
*
|
||||
* XXX: Heavy abuse of stream API. This needs a ring buffer.
|
||||
*/
|
||||
if (more && STREAM_WRITEABLE(peer->ibuf_work) < BGP_MAX_PACKET_SIZE) {
|
||||
void *from = stream_pnt(peer->ibuf_work);
|
||||
void *to = peer->ibuf_work->data;
|
||||
size_t siz = STREAM_READABLE(peer->ibuf_work);
|
||||
memmove(to, from, siz);
|
||||
stream_set_getp(peer->ibuf_work, 0);
|
||||
stream_set_endp(peer->ibuf_work, siz);
|
||||
}
|
||||
|
||||
assert(STREAM_WRITEABLE(peer->ibuf_work) >= BGP_MAX_PACKET_SIZE);
|
||||
assert(ringbuf_space(peer->ibuf_work) >= BGP_MAX_PACKET_SIZE);
|
||||
|
||||
/* handle invalid header */
|
||||
if (fatal) {
|
||||
/* wipe buffer just in case someone screwed up */
|
||||
stream_reset(peer->ibuf_work);
|
||||
ringbuf_wipe(peer->ibuf_work);
|
||||
} else {
|
||||
thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
|
||||
&peer->t_read);
|
||||
@ -474,14 +449,16 @@ static uint16_t bgp_read(struct peer *peer)
|
||||
size_t readsize; // how many bytes we want to read
|
||||
ssize_t nbytes; // how many bytes we actually read
|
||||
uint16_t status = 0;
|
||||
static uint8_t ibw[BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX];
|
||||
|
||||
readsize = STREAM_WRITEABLE(peer->ibuf_work);
|
||||
readsize = MIN(ringbuf_space(peer->ibuf_work), sizeof(ibw));
|
||||
nbytes = read(peer->fd, ibw, readsize);
|
||||
|
||||
nbytes = stream_read_try(peer->ibuf_work, peer->fd, readsize);
|
||||
|
||||
switch (nbytes) {
|
||||
/* EAGAIN or EWOULDBLOCK; come back later */
|
||||
if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
|
||||
SET_FLAG(status, BGP_IO_TRANS_ERR);
|
||||
/* Fatal error; tear down session */
|
||||
case -1:
|
||||
} else if (nbytes < 0) {
|
||||
zlog_err("%s [Error] bgp_read_packet error: %s", peer->host,
|
||||
safe_strerror(errno));
|
||||
|
||||
@ -495,10 +472,8 @@ static uint16_t bgp_read(struct peer *peer)
|
||||
|
||||
BGP_EVENT_ADD(peer, TCP_fatal_error);
|
||||
SET_FLAG(status, BGP_IO_FATAL_ERR);
|
||||
break;
|
||||
|
||||
/* Received EOF / TCP session closed */
|
||||
case 0:
|
||||
} else if (nbytes == 0) {
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug("%s [Event] BGP connection closed fd %d",
|
||||
peer->host, peer->fd);
|
||||
@ -513,14 +488,9 @@ static uint16_t bgp_read(struct peer *peer)
|
||||
|
||||
BGP_EVENT_ADD(peer, TCP_connection_closed);
|
||||
SET_FLAG(status, BGP_IO_FATAL_ERR);
|
||||
break;
|
||||
|
||||
/* EAGAIN or EWOULDBLOCK; come back later */
|
||||
case -2:
|
||||
SET_FLAG(status, BGP_IO_TRANS_ERR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} else {
|
||||
assert(ringbuf_put(peer->ibuf_work, ibw, nbytes)
|
||||
== (size_t)nbytes);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -529,27 +499,35 @@ static uint16_t bgp_read(struct peer *peer)
|
||||
/*
|
||||
* Called after we have read a BGP packet header. Validates marker, message
|
||||
* type and packet length. If any of these aren't correct, sends a notify.
|
||||
*
|
||||
* Assumes that there are at least BGP_HEADER_SIZE readable bytes in the input
|
||||
* buffer.
|
||||
*/
|
||||
static bool validate_header(struct peer *peer)
|
||||
{
|
||||
uint16_t size;
|
||||
uint8_t type;
|
||||
struct stream *pkt = peer->ibuf_work;
|
||||
size_t getp = stream_get_getp(pkt);
|
||||
struct ringbuf *pkt = peer->ibuf_work;
|
||||
|
||||
static uint8_t marker[BGP_MARKER_SIZE] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
static uint8_t m_correct[BGP_MARKER_SIZE] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
uint8_t m_rx[BGP_MARKER_SIZE] = {0x00};
|
||||
|
||||
if (memcmp(marker, stream_pnt(pkt), BGP_MARKER_SIZE) != 0) {
|
||||
if (ringbuf_peek(pkt, 0, m_rx, BGP_MARKER_SIZE) != BGP_MARKER_SIZE)
|
||||
return false;
|
||||
|
||||
if (memcmp(m_correct, m_rx, BGP_MARKER_SIZE) != 0) {
|
||||
bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR,
|
||||
BGP_NOTIFY_HEADER_NOT_SYNC);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get size and type in host byte order. */
|
||||
size = stream_getw_from(pkt, getp + BGP_MARKER_SIZE);
|
||||
type = stream_getc_from(pkt, getp + BGP_MARKER_SIZE + 2);
|
||||
/* Get size and type in network byte order. */
|
||||
ringbuf_peek(pkt, BGP_MARKER_SIZE, &size, sizeof(size));
|
||||
ringbuf_peek(pkt, BGP_MARKER_SIZE + 2, &type, sizeof(type));
|
||||
|
||||
size = ntohs(size);
|
||||
|
||||
/* BGP type check. */
|
||||
if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
|
||||
|
@ -36,6 +36,16 @@
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -595,6 +595,7 @@ static int bgp_write_notify(struct peer *peer)
|
||||
assert(type == BGP_MSG_NOTIFY);
|
||||
|
||||
/* Type should be notify. */
|
||||
atomic_fetch_add_explicit(&peer->notify_out, 1, memory_order_relaxed);
|
||||
peer->notify_out++;
|
||||
|
||||
/* Double start timer. */
|
||||
@ -1682,7 +1683,7 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size)
|
||||
}
|
||||
|
||||
/* peer count update */
|
||||
peer->notify_in++;
|
||||
atomic_fetch_add_explicit(&peer->notify_in, 1, memory_order_relaxed);
|
||||
|
||||
peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
|
||||
|
||||
@ -2192,7 +2193,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
*/
|
||||
switch (type) {
|
||||
case BGP_MSG_OPEN:
|
||||
peer->open_in++;
|
||||
atomic_fetch_add_explicit(&peer->open_in, 1,
|
||||
memory_order_relaxed);
|
||||
mprc = bgp_open_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
zlog_err(
|
||||
@ -2200,7 +2202,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
__FUNCTION__, peer->host);
|
||||
break;
|
||||
case BGP_MSG_UPDATE:
|
||||
peer->update_in++;
|
||||
atomic_fetch_add_explicit(&peer->update_in, 1,
|
||||
memory_order_relaxed);
|
||||
peer->readtime = monotime(NULL);
|
||||
mprc = bgp_update_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
@ -2209,7 +2212,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
__FUNCTION__, peer->host);
|
||||
break;
|
||||
case BGP_MSG_NOTIFY:
|
||||
peer->notify_in++;
|
||||
atomic_fetch_add_explicit(&peer->notify_in, 1,
|
||||
memory_order_relaxed);
|
||||
mprc = bgp_notify_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
zlog_err(
|
||||
@ -2218,7 +2222,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
break;
|
||||
case BGP_MSG_KEEPALIVE:
|
||||
peer->readtime = monotime(NULL);
|
||||
peer->keepalive_in++;
|
||||
atomic_fetch_add_explicit(&peer->keepalive_in, 1,
|
||||
memory_order_relaxed);
|
||||
mprc = bgp_keepalive_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
zlog_err(
|
||||
@ -2227,7 +2232,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
break;
|
||||
case BGP_MSG_ROUTE_REFRESH_NEW:
|
||||
case BGP_MSG_ROUTE_REFRESH_OLD:
|
||||
peer->refresh_in++;
|
||||
atomic_fetch_add_explicit(&peer->refresh_in, 1,
|
||||
memory_order_relaxed);
|
||||
mprc = bgp_route_refresh_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
zlog_err(
|
||||
@ -2235,7 +2241,8 @@ int bgp_process_packet(struct thread *thread)
|
||||
__FUNCTION__, peer->host);
|
||||
break;
|
||||
case BGP_MSG_CAPABILITY:
|
||||
peer->dynamic_cap_in++;
|
||||
atomic_fetch_add_explicit(&peer->dynamic_cap_in, 1,
|
||||
memory_order_relaxed);
|
||||
mprc = bgp_capability_receive(peer, size);
|
||||
if (mprc == BGP_Stop)
|
||||
zlog_err(
|
||||
|
674
bgpd/bgp_route.c
674
bgpd/bgp_route.c
@ -74,6 +74,9 @@
|
||||
#include "bgpd/bgp_evpn.h"
|
||||
#include "bgpd/bgp_evpn_vty.h"
|
||||
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "bgpd/bgp_route_clippy.c"
|
||||
#endif
|
||||
|
||||
/* Extern from bgp_dump.c */
|
||||
extern const char *bgp_origin_str[];
|
||||
@ -4488,9 +4491,9 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
|
||||
|
||||
/* Configure static BGP network. When user don't run zebra, static
|
||||
route should be installed as valid. */
|
||||
static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi,
|
||||
safi_t safi, const char *rmap, int backdoor,
|
||||
u_int32_t label_index)
|
||||
static int bgp_static_set(struct vty *vty, const char *negate,
|
||||
const char *ip_str, afi_t afi, safi_t safi,
|
||||
const char *rmap, int backdoor, u_int32_t label_index)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
int ret;
|
||||
@ -4512,113 +4515,110 @@ static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi,
|
||||
|
||||
apply_mask(&p);
|
||||
|
||||
/* Set BGP static route configuration. */
|
||||
rn = bgp_node_get(bgp->route[afi][safi], &p);
|
||||
if (negate) {
|
||||
|
||||
if (rn->info) {
|
||||
/* Configuration change. */
|
||||
bgp_static = rn->info;
|
||||
/* Set BGP static route configuration. */
|
||||
rn = bgp_node_lookup(bgp->route[afi][safi], &p);
|
||||
|
||||
/* Label index cannot be changed. */
|
||||
if (bgp_static->label_index != label_index) {
|
||||
vty_out(vty, "%% Label index cannot be changed\n");
|
||||
if (!rn) {
|
||||
vty_out(vty,
|
||||
"%% Can't find static route specified\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Check previous routes are installed into BGP. */
|
||||
if (bgp_static->valid && bgp_static->backdoor != backdoor)
|
||||
need_update = 1;
|
||||
bgp_static = rn->info;
|
||||
|
||||
bgp_static->backdoor = backdoor;
|
||||
|
||||
if (rmap) {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
bgp_static->rmap.map = route_map_lookup_by_name(rmap);
|
||||
} else {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name = NULL;
|
||||
bgp_static->rmap.map = NULL;
|
||||
bgp_static->valid = 0;
|
||||
if ((label_index != BGP_INVALID_LABEL_INDEX)
|
||||
&& (label_index != bgp_static->label_index)) {
|
||||
vty_out(vty,
|
||||
"%% label-index doesn't match static route\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if ((rmap && bgp_static->rmap.name)
|
||||
&& strcmp(rmap, bgp_static->rmap.name)) {
|
||||
vty_out(vty,
|
||||
"%% route-map name doesn't match static route\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Update BGP RIB. */
|
||||
if (!bgp_static->backdoor)
|
||||
bgp_static_withdraw(bgp, &p, afi, safi);
|
||||
|
||||
/* Clear configuration. */
|
||||
bgp_static_free(bgp_static);
|
||||
rn->info = NULL;
|
||||
bgp_unlock_node(rn);
|
||||
bgp_unlock_node(rn);
|
||||
} else {
|
||||
/* New configuration. */
|
||||
bgp_static = bgp_static_new();
|
||||
bgp_static->backdoor = backdoor;
|
||||
bgp_static->valid = 0;
|
||||
bgp_static->igpmetric = 0;
|
||||
bgp_static->igpnexthop.s_addr = 0;
|
||||
bgp_static->label_index = label_index;
|
||||
|
||||
if (rmap) {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
bgp_static->rmap.map = route_map_lookup_by_name(rmap);
|
||||
/* Set BGP static route configuration. */
|
||||
rn = bgp_node_get(bgp->route[afi][safi], &p);
|
||||
|
||||
if (rn->info) {
|
||||
/* Configuration change. */
|
||||
bgp_static = rn->info;
|
||||
|
||||
/* Label index cannot be changed. */
|
||||
if (bgp_static->label_index != label_index) {
|
||||
vty_out(vty, "%% cannot change label-index\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Check previous routes are installed into BGP. */
|
||||
if (bgp_static->valid &&
|
||||
bgp_static->backdoor != backdoor)
|
||||
need_update = 1;
|
||||
|
||||
bgp_static->backdoor = backdoor;
|
||||
|
||||
if (rmap) {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
bgp_static->rmap.map =
|
||||
route_map_lookup_by_name(rmap);
|
||||
} else {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name = NULL;
|
||||
bgp_static->rmap.map = NULL;
|
||||
bgp_static->valid = 0;
|
||||
}
|
||||
bgp_unlock_node(rn);
|
||||
} else {
|
||||
/* New configuration. */
|
||||
bgp_static = bgp_static_new();
|
||||
bgp_static->backdoor = backdoor;
|
||||
bgp_static->valid = 0;
|
||||
bgp_static->igpmetric = 0;
|
||||
bgp_static->igpnexthop.s_addr = 0;
|
||||
bgp_static->label_index = label_index;
|
||||
|
||||
if (rmap) {
|
||||
if (bgp_static->rmap.name)
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||
bgp_static->rmap.name);
|
||||
bgp_static->rmap.name =
|
||||
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
|
||||
bgp_static->rmap.map =
|
||||
route_map_lookup_by_name(rmap);
|
||||
}
|
||||
rn->info = bgp_static;
|
||||
}
|
||||
rn->info = bgp_static;
|
||||
|
||||
bgp_static->valid = 1;
|
||||
if (need_update)
|
||||
bgp_static_withdraw(bgp, &p, afi, safi);
|
||||
|
||||
if (!bgp_static->backdoor)
|
||||
bgp_static_update(bgp, &p, bgp_static, afi, safi);
|
||||
}
|
||||
|
||||
bgp_static->valid = 1;
|
||||
if (need_update)
|
||||
bgp_static_withdraw(bgp, &p, afi, safi);
|
||||
|
||||
if (!bgp_static->backdoor)
|
||||
bgp_static_update(bgp, &p, bgp_static, afi, safi);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Configure static BGP network. */
|
||||
static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
int ret;
|
||||
struct prefix p;
|
||||
struct bgp_static *bgp_static;
|
||||
struct bgp_node *rn;
|
||||
|
||||
/* Convert IP prefix string to struct prefix. */
|
||||
ret = str2prefix(ip_str, &p);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Malformed prefix\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
|
||||
vty_out(vty, "%% Malformed prefix (link-local address)\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
apply_mask(&p);
|
||||
|
||||
rn = bgp_node_lookup(bgp->route[afi][safi], &p);
|
||||
if (!rn) {
|
||||
vty_out(vty,
|
||||
"%% Can't find specified static route configuration.\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
bgp_static = rn->info;
|
||||
|
||||
/* Update BGP RIB. */
|
||||
if (!bgp_static->backdoor)
|
||||
bgp_static_withdraw(bgp, &p, afi, safi);
|
||||
|
||||
/* Clear configuration. */
|
||||
bgp_static_free(bgp_static);
|
||||
rn->info = NULL;
|
||||
bgp_unlock_node(rn);
|
||||
bgp_unlock_node(rn);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -5044,387 +5044,62 @@ DEFUN (no_bgp_table_map,
|
||||
argv[idx_word]->arg);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network,
|
||||
bgp_network_cmd,
|
||||
"network A.B.C.D/M",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv4 prefix\n")
|
||||
DEFPY(bgp_network,
|
||||
bgp_network_cmd,
|
||||
"[no] network \
|
||||
<A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
|
||||
[{route-map WORD$map_name|label-index (0-1048560)$label_index| \
|
||||
backdoor$backdoor}]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv4 prefix\n"
|
||||
"Network number\n"
|
||||
"Network mask\n"
|
||||
"Network mask\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n"
|
||||
"Specify a BGP backdoor route\n")
|
||||
{
|
||||
int idx_ipv4_prefixlen = 1;
|
||||
return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
|
||||
bgp_node_safi(vty), NULL, 0,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
char addr_prefix_str[BUFSIZ];
|
||||
|
||||
DEFUN (bgp_network_route_map,
|
||||
bgp_network_route_map_cmd,
|
||||
"network A.B.C.D/M route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv4 prefix\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv4_prefixlen = 1;
|
||||
int idx_word = 3;
|
||||
return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
|
||||
bgp_node_safi(vty), argv[idx_word]->arg, 0,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
if (address_str) {
|
||||
int ret;
|
||||
|
||||
DEFUN (bgp_network_backdoor,
|
||||
bgp_network_backdoor_cmd,
|
||||
"network A.B.C.D/M backdoor",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv4 prefix\n"
|
||||
"Specify a BGP backdoor route\n")
|
||||
{
|
||||
int idx_ipv4_prefixlen = 1;
|
||||
return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
|
||||
SAFI_UNICAST, NULL, 1, BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask,
|
||||
bgp_network_mask_cmd,
|
||||
"network A.B.C.D mask A.B.C.D",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Network mask\n"
|
||||
"Network mask\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int idx_ipv4_2 = 3;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
|
||||
prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
ret = netmask_str2prefix_str(address_str, netmask_str,
|
||||
addr_prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
|
||||
0, BGP_INVALID_LABEL_INDEX);
|
||||
return bgp_static_set(vty, no, address_str ? addr_prefix_str:prefix_str,
|
||||
AFI_IP, bgp_node_safi(vty),
|
||||
map_name, backdoor?1:0,
|
||||
label_index ?
|
||||
(uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask_route_map,
|
||||
bgp_network_mask_route_map_cmd,
|
||||
"network A.B.C.D mask A.B.C.D route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Network mask\n"
|
||||
"Network mask\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
DEFPY(ipv6_bgp_network,
|
||||
ipv6_bgp_network_cmd,
|
||||
"[no] network X:X::X:X/M$prefix \
|
||||
[{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int idx_ipv4_2 = 3;
|
||||
int idx_word = 5;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
|
||||
prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
|
||||
argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
|
||||
return bgp_static_set(vty, no, prefix_str, AFI_IP6,
|
||||
bgp_node_safi(vty), map_name, 0,
|
||||
label_index ?
|
||||
(uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask_backdoor,
|
||||
bgp_network_mask_backdoor_cmd,
|
||||
"network A.B.C.D mask A.B.C.D backdoor",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Network mask\n"
|
||||
"Network mask\n"
|
||||
"Specify a BGP backdoor route\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int idx_ipv4_2 = 3;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
|
||||
prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask_natural,
|
||||
bgp_network_mask_natural_cmd,
|
||||
"network A.B.C.D",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL,
|
||||
0, BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask_natural_route_map,
|
||||
bgp_network_mask_natural_route_map_cmd,
|
||||
"network A.B.C.D route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int idx_word = 3;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
|
||||
argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_mask_natural_backdoor,
|
||||
bgp_network_mask_natural_backdoor_cmd,
|
||||
"network A.B.C.D backdoor",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Specify a BGP backdoor route\n")
|
||||
{
|
||||
int idx_ipv4 = 1;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_label_index,
|
||||
bgp_network_label_index_cmd,
|
||||
"network A.B.C.D/M label-index (0-1048560)",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n")
|
||||
{
|
||||
u_int32_t label_index;
|
||||
|
||||
label_index = strtoul(argv[3]->arg, NULL, 10);
|
||||
return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
|
||||
NULL, 0, label_index);
|
||||
}
|
||||
|
||||
DEFUN (bgp_network_label_index_route_map,
|
||||
bgp_network_label_index_route_map_cmd,
|
||||
"network A.B.C.D/M label-index (0-1048560) route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IP prefix\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
u_int32_t label_index;
|
||||
|
||||
label_index = strtoul(argv[3]->arg, NULL, 10);
|
||||
return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty),
|
||||
argv[5]->arg, 0, label_index);
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_network,
|
||||
no_bgp_network_cmd,
|
||||
"no network A.B.C.D/M [<backdoor|route-map WORD>]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv4 prefix\n"
|
||||
"Specify a BGP backdoor route\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv4_prefixlen = 2;
|
||||
return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP,
|
||||
bgp_node_safi(vty));
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_network_mask,
|
||||
no_bgp_network_mask_cmd,
|
||||
"no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Network mask\n"
|
||||
"Network mask\n"
|
||||
"Specify a BGP backdoor route\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv4 = 2;
|
||||
int idx_ipv4_2 = 4;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
|
||||
prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_network_mask_natural,
|
||||
no_bgp_network_mask_natural_cmd,
|
||||
"no network A.B.C.D [<backdoor|route-map WORD>]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"Network number\n"
|
||||
"Specify a BGP backdoor route\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv4 = 2;
|
||||
int ret;
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str);
|
||||
if (!ret) {
|
||||
vty_out(vty, "%% Inconsistent address and mask\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
|
||||
}
|
||||
|
||||
ALIAS(no_bgp_network, no_bgp_network_label_index_cmd,
|
||||
"no network A.B.C.D/M label-index (0-1048560)", NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n")
|
||||
|
||||
ALIAS(no_bgp_network, no_bgp_network_label_index_route_map_cmd,
|
||||
"no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IP prefix\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
|
||||
DEFUN (ipv6_bgp_network,
|
||||
ipv6_bgp_network_cmd,
|
||||
"network X:X::X:X/M",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n")
|
||||
{
|
||||
int idx_ipv6_prefixlen = 1;
|
||||
return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
|
||||
bgp_node_safi(vty), NULL, 0,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (ipv6_bgp_network_route_map,
|
||||
ipv6_bgp_network_route_map_cmd,
|
||||
"network X:X::X:X/M route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv6_prefixlen = 1;
|
||||
int idx_word = 3;
|
||||
return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
|
||||
bgp_node_safi(vty), argv[idx_word]->arg, 0,
|
||||
BGP_INVALID_LABEL_INDEX);
|
||||
}
|
||||
|
||||
DEFUN (ipv6_bgp_network_label_index,
|
||||
ipv6_bgp_network_label_index_cmd,
|
||||
"network X:X::X:X/M label-index (0-1048560)",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix <network>/<length>\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n")
|
||||
{
|
||||
u_int32_t label_index;
|
||||
|
||||
label_index = strtoul(argv[3]->arg, NULL, 10);
|
||||
return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
|
||||
NULL, 0, label_index);
|
||||
}
|
||||
|
||||
DEFUN (ipv6_bgp_network_label_index_route_map,
|
||||
ipv6_bgp_network_label_index_route_map_cmd,
|
||||
"network X:X::X:X/M label-index (0-1048560) route-map WORD",
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
u_int32_t label_index;
|
||||
|
||||
label_index = strtoul(argv[3]->arg, NULL, 10);
|
||||
return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty),
|
||||
argv[5]->arg, 0, label_index);
|
||||
}
|
||||
|
||||
DEFUN (no_ipv6_bgp_network,
|
||||
no_ipv6_bgp_network_cmd,
|
||||
"no network X:X::X:X/M [route-map WORD]",
|
||||
NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
{
|
||||
int idx_ipv6_prefixlen = 2;
|
||||
return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
|
||||
bgp_node_safi(vty));
|
||||
}
|
||||
|
||||
ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_cmd,
|
||||
"no network X:X::X:X/M label-index (0-1048560)", NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix <network>/<length>\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n")
|
||||
|
||||
ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_route_map_cmd,
|
||||
"no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
|
||||
"Specify a network to announce via BGP\n"
|
||||
"IPv6 prefix\n"
|
||||
"Label index to associate with the prefix\n"
|
||||
"Label index value\n"
|
||||
"Route-map to modify the attributes\n"
|
||||
"Name of the route map\n")
|
||||
|
||||
/* Aggreagete address:
|
||||
|
||||
advertise-map Set condition to advertise attribute
|
||||
@ -8402,8 +8077,9 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||
vty_out(vty, ",\"%s\": ", buf2);
|
||||
|
||||
vty_out(vty, "%s",
|
||||
json_object_to_json_string_ext(json_paths, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_to_json_string(json_paths));
|
||||
json_object_free(json_paths);
|
||||
json_paths = NULL;
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
@ -8417,7 +8093,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||
*total_cum = total_count;
|
||||
}
|
||||
if (use_json) {
|
||||
json_object_free(json_paths);
|
||||
if (json_paths)
|
||||
json_object_free(json_paths);
|
||||
if (is_last)
|
||||
vty_out(vty, " } }\n");
|
||||
else
|
||||
@ -11162,10 +10839,10 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
|
||||
if (bgp_static->rmap.name)
|
||||
vty_out(vty, " route-map %s",
|
||||
bgp_static->rmap.name);
|
||||
else {
|
||||
if (bgp_static->backdoor)
|
||||
vty_out(vty, " backdoor");
|
||||
}
|
||||
|
||||
if (bgp_static->backdoor)
|
||||
vty_out(vty, " backdoor");
|
||||
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
@ -11298,10 +10975,9 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
|
||||
if (bgp_static->rmap.name)
|
||||
vty_out(vty, " route-map %s", bgp_static->rmap.name);
|
||||
else {
|
||||
if (bgp_static->backdoor)
|
||||
vty_out(vty, " backdoor");
|
||||
}
|
||||
|
||||
if (bgp_static->backdoor)
|
||||
vty_out(vty, " backdoor");
|
||||
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
@ -11384,18 +11060,7 @@ void bgp_route_init(void)
|
||||
/* IPv4 BGP commands. */
|
||||
install_element(BGP_NODE, &bgp_table_map_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_natural_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_route_map_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_route_map_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_backdoor_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd);
|
||||
install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
|
||||
install_element(BGP_NODE, &no_bgp_table_map_cmd);
|
||||
install_element(BGP_NODE, &no_bgp_network_cmd);
|
||||
install_element(BGP_NODE, &no_bgp_network_mask_cmd);
|
||||
install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd);
|
||||
|
||||
install_element(BGP_NODE, &aggregate_address_cmd);
|
||||
install_element(BGP_NODE, &aggregate_address_mask_cmd);
|
||||
@ -11405,20 +11070,7 @@ void bgp_route_init(void)
|
||||
/* IPv4 unicast configuration. */
|
||||
install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_label_index_cmd);
|
||||
install_element(BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
|
||||
install_element(BGP_IPV4_NODE,
|
||||
&no_bgp_network_label_index_route_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
|
||||
install_element(BGP_IPV4_NODE, &no_bgp_network_cmd);
|
||||
install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
|
||||
install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
|
||||
|
||||
install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
|
||||
install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
|
||||
@ -11428,16 +11080,7 @@ void bgp_route_init(void)
|
||||
/* IPv4 multicast configuration. */
|
||||
install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE,
|
||||
&bgp_network_mask_natural_route_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
|
||||
install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
|
||||
@ -11480,21 +11123,12 @@ void bgp_route_init(void)
|
||||
/* New config IPv6 BGP commands. */
|
||||
install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
|
||||
install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
|
||||
install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
|
||||
install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
|
||||
install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
|
||||
install_element(BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
|
||||
install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
|
||||
install_element(BGP_IPV6_NODE,
|
||||
&ipv6_bgp_network_label_index_route_map_cmd);
|
||||
install_element(BGP_IPV6_NODE,
|
||||
&no_ipv6_bgp_network_label_index_route_map_cmd);
|
||||
|
||||
install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
|
||||
install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
|
||||
|
||||
install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
|
||||
install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
|
||||
|
||||
install_element(BGP_NODE, &bgp_distance_cmd);
|
||||
install_element(BGP_NODE, &no_bgp_distance_cmd);
|
||||
|
@ -512,6 +512,7 @@ static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length,
|
||||
{
|
||||
static struct in_addr addr;
|
||||
struct peer *peer;
|
||||
uint32_t ui, uo;
|
||||
|
||||
if (smux_header_table(v, name, length, exact, var_len, write_method)
|
||||
== MATCH_FAILED)
|
||||
@ -571,21 +572,20 @@ static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length,
|
||||
return SNMP_INTEGER(peer->as);
|
||||
break;
|
||||
case BGPPEERINUPDATES:
|
||||
return SNMP_INTEGER(peer->update_in);
|
||||
ui = atomic_load_explicit(&peer->update_in,
|
||||
memory_order_relaxed);
|
||||
return SNMP_INTEGER(ui);
|
||||
break;
|
||||
case BGPPEEROUTUPDATES:
|
||||
return SNMP_INTEGER(peer->update_out);
|
||||
uo = atomic_load_explicit(&peer->update_out,
|
||||
memory_order_relaxed);
|
||||
return SNMP_INTEGER(uo);
|
||||
break;
|
||||
case BGPPEERINTOTALMESSAGES:
|
||||
return SNMP_INTEGER(peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in + peer->notify_in
|
||||
+ peer->refresh_in + peer->dynamic_cap_in);
|
||||
return SNMP_INTEGER(PEER_TOTAL_RX(peer));
|
||||
break;
|
||||
case BGPPEEROUTTOTALMESSAGES:
|
||||
return SNMP_INTEGER(peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out + peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out);
|
||||
return SNMP_INTEGER(PEER_TOTAL_TX(peer));
|
||||
break;
|
||||
case BGPPEERLASTERROR: {
|
||||
static u_char lasterror[2];
|
||||
|
183
bgpd/bgp_vty.c
183
bgpd/bgp_vty.c
@ -1438,7 +1438,7 @@ DEFUN (no_bgp_rpkt_quanta,
|
||||
|
||||
void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
|
||||
{
|
||||
if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
|
||||
if (!bgp->heuristic_coalesce)
|
||||
vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
|
||||
}
|
||||
|
||||
@ -1453,6 +1453,7 @@ DEFUN (bgp_coalesce_time,
|
||||
|
||||
int idx = 0;
|
||||
argv_find(argv, argc, "(0-4294967295)", &idx);
|
||||
bgp->heuristic_coalesce = false;
|
||||
bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -1466,6 +1467,7 @@ DEFUN (no_bgp_coalesce_time,
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||
|
||||
bgp->heuristic_coalesce = true;
|
||||
bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -7074,17 +7076,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
json_object_int_add(json_peer, "remoteAs", peer->as);
|
||||
json_object_int_add(json_peer, "version", 4);
|
||||
json_object_int_add(json_peer, "msgRcvd",
|
||||
peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in
|
||||
+ peer->notify_in
|
||||
+ peer->refresh_in
|
||||
+ peer->dynamic_cap_in);
|
||||
PEER_TOTAL_RX(peer));
|
||||
json_object_int_add(json_peer, "msgSent",
|
||||
peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out
|
||||
+ peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out);
|
||||
PEER_TOTAL_TX(peer));
|
||||
|
||||
json_object_int_add(json_peer, "tableVersion",
|
||||
peer->version[afi][safi]);
|
||||
@ -7141,48 +7135,18 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
" ");
|
||||
|
||||
vty_out(vty, "4 %10u %7u %7u %8" PRIu64 " %4d %4zd %8s",
|
||||
peer->as,
|
||||
atomic_load_explicit(&peer->open_in,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->update_in,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->keepalive_in,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->notify_in,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->refresh_in,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->dynamic_cap_in,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&peer->open_out,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->update_out,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->keepalive_out,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->notify_out,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->refresh_out,
|
||||
memory_order_relaxed)
|
||||
+ atomic_load_explicit(
|
||||
&peer->dynamic_cap_out,
|
||||
memory_order_relaxed),
|
||||
peer->version[afi][safi], 0, peer->obuf->count,
|
||||
peer->as, PEER_TOTAL_RX(peer),
|
||||
PEER_TOTAL_TX(peer), peer->version[afi][safi],
|
||||
0, peer->obuf->count,
|
||||
peer_uptime(peer->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, 0, NULL));
|
||||
|
||||
if (peer->status == Established)
|
||||
vty_out(vty, " %12ld",
|
||||
peer->pcount[afi][pfx_rcd_safi]);
|
||||
if (peer->afc_recv[afi][pfx_rcd_safi])
|
||||
vty_out(vty, " %12ld",
|
||||
peer->pcount[afi][pfx_rcd_safi]);
|
||||
else
|
||||
vty_out(vty, " NoNeg");
|
||||
else {
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
|
||||
vty_out(vty, " Idle (Admin)");
|
||||
@ -8309,17 +8273,29 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
|
||||
if (p->status == Established) {
|
||||
time_t uptime;
|
||||
struct tm *tm;
|
||||
|
||||
uptime = bgp_clock();
|
||||
uptime -= p->uptime;
|
||||
tm = gmtime(&uptime);
|
||||
epoch_tbuf = time(NULL) - uptime;
|
||||
|
||||
#if CONFDATE > 20200101
|
||||
CPP_NOTICE("bgpTimerUp should be deprecated and can be removed now");
|
||||
#endif
|
||||
/*
|
||||
* bgpTimerUp was miliseconds that was accurate
|
||||
* up to 1 day, then the value returned
|
||||
* became garbage. So in order to provide
|
||||
* some level of backwards compatability,
|
||||
* we still provde the data, but now
|
||||
* we are returning the correct value
|
||||
* and also adding a new bgpTimerUpMsec
|
||||
* which will allow us to deprecate
|
||||
* this eventually
|
||||
*/
|
||||
json_object_int_add(json_neigh, "bgpTimerUp",
|
||||
(tm->tm_sec * 1000)
|
||||
+ (tm->tm_min * 60000)
|
||||
+ (tm->tm_hour * 3600000));
|
||||
uptime * 1000);
|
||||
json_object_int_add(json_neigh, "bgpTimerUpMsec",
|
||||
uptime * 1000);
|
||||
json_object_string_add(json_neigh, "bgpTimerUpString",
|
||||
peer_uptime(p->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, 0,
|
||||
@ -9350,34 +9326,44 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
json_object_int_add(json_stat, "depthInq", 0);
|
||||
json_object_int_add(json_stat, "depthOutq",
|
||||
(unsigned long)p->obuf->count);
|
||||
json_object_int_add(json_stat, "opensSent", p->open_out);
|
||||
json_object_int_add(json_stat, "opensRecv", p->open_in);
|
||||
json_object_int_add(json_stat, "opensSent",
|
||||
atomic_load_explicit(&p->open_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "opensRecv",
|
||||
atomic_load_explicit(&p->open_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "notificationsSent",
|
||||
p->notify_out);
|
||||
atomic_load_explicit(&p->notify_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "notificationsRecv",
|
||||
p->notify_in);
|
||||
json_object_int_add(json_stat, "updatesSent", p->update_out);
|
||||
json_object_int_add(json_stat, "updatesRecv", p->update_in);
|
||||
atomic_load_explicit(&p->notify_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "updatesSent",
|
||||
atomic_load_explicit(&p->update_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "updatesRecv",
|
||||
atomic_load_explicit(&p->update_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "keepalivesSent",
|
||||
p->keepalive_out);
|
||||
atomic_load_explicit(&p->keepalive_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "keepalivesRecv",
|
||||
p->keepalive_in);
|
||||
atomic_load_explicit(&p->keepalive_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "routeRefreshSent",
|
||||
p->refresh_out);
|
||||
atomic_load_explicit(&p->refresh_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "routeRefreshRecv",
|
||||
p->refresh_in);
|
||||
atomic_load_explicit(&p->refresh_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "capabilitySent",
|
||||
p->dynamic_cap_out);
|
||||
atomic_load_explicit(&p->dynamic_cap_out,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "capabilityRecv",
|
||||
p->dynamic_cap_in);
|
||||
json_object_int_add(json_stat, "totalSent",
|
||||
p->open_out + p->notify_out + p->update_out
|
||||
+ p->keepalive_out + p->refresh_out
|
||||
+ p->dynamic_cap_out);
|
||||
json_object_int_add(json_stat, "totalRecv",
|
||||
p->open_in + p->notify_in + p->update_in
|
||||
+ p->keepalive_in + p->refresh_in
|
||||
+ p->dynamic_cap_in);
|
||||
atomic_load_explicit(&p->dynamic_cap_in,
|
||||
memory_order_relaxed));
|
||||
json_object_int_add(json_stat, "totalSent", PEER_TOTAL_TX(p));
|
||||
json_object_int_add(json_stat, "totalRecv", PEER_TOTAL_RX(p));
|
||||
json_object_object_add(json_neigh, "messageStats", json_stat);
|
||||
} else {
|
||||
/* Packet counts. */
|
||||
@ -9386,25 +9372,38 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
|
||||
vty_out(vty, " Outq depth is %lu\n",
|
||||
(unsigned long)p->obuf->count);
|
||||
vty_out(vty, " Sent Rcvd\n");
|
||||
vty_out(vty, " Opens: %10d %10d\n", p->open_out,
|
||||
p->open_in);
|
||||
vty_out(vty, " Notifications: %10d %10d\n", p->notify_out,
|
||||
p->notify_in);
|
||||
vty_out(vty, " Updates: %10d %10d\n", p->update_out,
|
||||
p->update_in);
|
||||
vty_out(vty, " Keepalives: %10d %10d\n", p->keepalive_out,
|
||||
p->keepalive_in);
|
||||
vty_out(vty, " Route Refresh: %10d %10d\n", p->refresh_out,
|
||||
p->refresh_in);
|
||||
vty_out(vty, " Opens: %10d %10d\n",
|
||||
atomic_load_explicit(&p->open_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->open_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Notifications: %10d %10d\n",
|
||||
atomic_load_explicit(&p->notify_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->notify_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Updates: %10d %10d\n",
|
||||
atomic_load_explicit(&p->update_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->update_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Keepalives: %10d %10d\n",
|
||||
atomic_load_explicit(&p->keepalive_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->keepalive_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Route Refresh: %10d %10d\n",
|
||||
atomic_load_explicit(&p->refresh_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->refresh_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Capability: %10d %10d\n",
|
||||
p->dynamic_cap_out, p->dynamic_cap_in);
|
||||
vty_out(vty, " Total: %10d %10d\n",
|
||||
p->open_out + p->notify_out + p->update_out
|
||||
+ p->keepalive_out + p->refresh_out
|
||||
+ p->dynamic_cap_out,
|
||||
p->open_in + p->notify_in + p->update_in
|
||||
+ p->keepalive_in + p->refresh_in
|
||||
+ p->dynamic_cap_in);
|
||||
atomic_load_explicit(&p->dynamic_cap_out,
|
||||
memory_order_relaxed),
|
||||
atomic_load_explicit(&p->dynamic_cap_in,
|
||||
memory_order_relaxed));
|
||||
vty_out(vty, " Total: %10d %10d\n", PEER_TOTAL_TX(p),
|
||||
PEER_TOTAL_RX(p));
|
||||
}
|
||||
|
||||
if (use_json) {
|
||||
|
@ -1542,8 +1542,9 @@ void bgp_update_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id)
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
|
||||
if (vrf_bitmap_check(zclient->redist[afi][i],
|
||||
old_vrf_id)) {
|
||||
if ((old_vrf_id == VRF_UNKNOWN)
|
||||
|| vrf_bitmap_check(zclient->redist[afi][i],
|
||||
old_vrf_id)) {
|
||||
vrf_bitmap_unset(zclient->redist[afi][i],
|
||||
old_vrf_id);
|
||||
vrf_bitmap_set(zclient->redist[afi][i],
|
||||
|
24
bgpd/bgpd.c
24
bgpd/bgpd.c
@ -24,6 +24,7 @@
|
||||
#include "thread.h"
|
||||
#include "buffer.h"
|
||||
#include "stream.h"
|
||||
#include "ringbuf.h"
|
||||
#include "command.h"
|
||||
#include "sockunion.h"
|
||||
#include "sockopt.h"
|
||||
@ -1162,7 +1163,9 @@ struct peer *peer_new(struct bgp *bgp)
|
||||
*/
|
||||
peer->obuf_work =
|
||||
stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
|
||||
peer->ibuf_work = stream_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
|
||||
peer->ibuf_work =
|
||||
ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
|
||||
|
||||
peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
|
||||
|
||||
bgp_sync_init(peer);
|
||||
@ -1475,9 +1478,12 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
|
||||
hash_get(bgp->peerhash, peer, hash_alloc_intern);
|
||||
|
||||
/* Adjust update-group coalesce timer heuristics for # peers. */
|
||||
long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME
|
||||
+ (bgp->peer->count * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME);
|
||||
bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct);
|
||||
if (bgp->heuristic_coalesce) {
|
||||
long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME
|
||||
+ (bgp->peer->count
|
||||
* BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME);
|
||||
bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct);
|
||||
}
|
||||
|
||||
active = peer_active(peer);
|
||||
|
||||
@ -2176,7 +2182,7 @@ int peer_delete(struct peer *peer)
|
||||
}
|
||||
|
||||
if (peer->ibuf_work) {
|
||||
stream_free(peer->ibuf_work);
|
||||
ringbuf_del(peer->ibuf_work);
|
||||
peer->ibuf_work = NULL;
|
||||
}
|
||||
|
||||
@ -7481,7 +7487,15 @@ void bgp_pthreads_run()
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
|
||||
|
||||
/*
|
||||
* Please ensure that the io thread is running
|
||||
* by calling bgp_io_running. The BGP threads
|
||||
* depend on it being running when we start
|
||||
* looking for it.
|
||||
*/
|
||||
frr_pthread_run(PTHREAD_IO, &attr, NULL);
|
||||
bgp_io_running();
|
||||
|
||||
frr_pthread_run(PTHREAD_KEEPALIVES, &attr, NULL);
|
||||
}
|
||||
|
||||
|
26
bgpd/bgpd.h
26
bgpd/bgpd.h
@ -385,7 +385,10 @@ struct bgp {
|
||||
_Atomic uint32_t wpkt_quanta; // max # packets to write per i/o cycle
|
||||
_Atomic uint32_t rpkt_quanta; // max # packets to read per i/o cycle
|
||||
|
||||
u_int32_t coalesce_time;
|
||||
/* Automatic coalesce adjust on/off */
|
||||
bool heuristic_coalesce;
|
||||
/* Actual coalesce time */
|
||||
uint32_t coalesce_time;
|
||||
|
||||
u_int32_t addpath_tx_id;
|
||||
int addpath_tx_used[AFI_MAX][SAFI_MAX];
|
||||
@ -632,8 +635,8 @@ struct peer {
|
||||
struct stream_fifo *ibuf; // packets waiting to be processed
|
||||
struct stream_fifo *obuf; // packets waiting to be written
|
||||
|
||||
struct stream *ibuf_work; // WiP buffer used by bgp_read() only
|
||||
struct stream *obuf_work; // WiP buffer used to construct packets
|
||||
struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only
|
||||
struct stream *obuf_work; // WiP buffer used to construct packets
|
||||
|
||||
struct stream *curr; // the current packet being parsed
|
||||
|
||||
@ -863,6 +866,22 @@ struct peer {
|
||||
/* workqueues */
|
||||
struct work_queue *clear_node_queue;
|
||||
|
||||
#define PEER_TOTAL_RX(peer) \
|
||||
atomic_load_explicit(&peer->open_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->update_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->notify_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->refresh_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->keepalive_in, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->dynamic_cap_in, memory_order_relaxed)
|
||||
|
||||
#define PEER_TOTAL_TX(peer) \
|
||||
atomic_load_explicit(&peer->open_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->update_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->notify_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->refresh_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->keepalive_out, memory_order_relaxed) + \
|
||||
atomic_load_explicit(&peer->dynamic_cap_out, memory_order_relaxed)
|
||||
|
||||
/* Statistics field */
|
||||
_Atomic uint32_t open_in; /* Open message input count */
|
||||
_Atomic uint32_t open_out; /* Open message output count */
|
||||
@ -1054,6 +1073,7 @@ struct bgp_nlri {
|
||||
#define BGP_ATTR_AS4_PATH 17
|
||||
#define BGP_ATTR_AS4_AGGREGATOR 18
|
||||
#define BGP_ATTR_AS_PATHLIMIT 21
|
||||
#define BGP_ATTR_PMSI_TUNNEL 22
|
||||
#define BGP_ATTR_ENCAP 23
|
||||
#define BGP_ATTR_LARGE_COMMUNITIES 32
|
||||
#define BGP_ATTR_PREFIX_SID 40
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "lib/linklist.h"
|
||||
#include "lib/command.h"
|
||||
#include "lib/stream.h"
|
||||
#include "lib/ringbuf.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_ecommunity.h"
|
||||
@ -1310,7 +1311,7 @@ static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp,
|
||||
stream_fifo_free(rfd->peer->obuf);
|
||||
|
||||
if (rfd->peer->ibuf_work)
|
||||
stream_free(rfd->peer->ibuf_work);
|
||||
ringbuf_del(rfd->peer->ibuf_work);
|
||||
if (rfd->peer->obuf_work)
|
||||
stream_free(rfd->peer->obuf_work);
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "lib/command.h"
|
||||
#include "lib/zclient.h"
|
||||
#include "lib/stream.h"
|
||||
#include "lib/ringbuf.h"
|
||||
#include "lib/memory.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
@ -198,7 +199,7 @@ static void vnc_redistribute_add(struct prefix *p, u_int32_t metric,
|
||||
stream_fifo_free(vncHD1VR.peer->obuf);
|
||||
|
||||
if (vncHD1VR.peer->ibuf_work)
|
||||
stream_free(vncHD1VR.peer->ibuf_work);
|
||||
ringbuf_del(vncHD1VR.peer->ibuf_work);
|
||||
if (vncHD1VR.peer->obuf_work)
|
||||
stream_free(vncHD1VR.peer->obuf_work);
|
||||
|
||||
|
26
configure.ac
26
configure.ac
@ -40,7 +40,7 @@ AS_IF([test "$host" != "$build"], [
|
||||
( CPPFLAGS="$HOST_CPPFLAGS"; \
|
||||
CFLAGS="$HOST_CFLAGS"; \
|
||||
LDFLAGS="$HOST_LDFLAGS"; \
|
||||
cd hosttools; "${abssrc}/configure" "--host=$build" "--build=$build"; )
|
||||
cd hosttools; "${abssrc}/configure" "--host=$build" "--build=$build" "--enable-clippy-only" "--disable-nhrpd" "--disable-vtysh"; )
|
||||
|
||||
AC_MSG_NOTICE([...])
|
||||
AC_MSG_NOTICE([... cross-compilation: finished self-configuring for build platform tools])
|
||||
@ -354,6 +354,8 @@ AC_ARG_ENABLE(logfile_mask,
|
||||
AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files]))
|
||||
AC_ARG_ENABLE(shell_access,
|
||||
AS_HELP_STRING([--enable-shell-access], [Allow users to access shell/telnet/ssh]))
|
||||
AC_ARG_ENABLE(realms,
|
||||
AS_HELP_STRING([--enable-realms], [enable REALMS support under Linux]))
|
||||
AC_ARG_ENABLE(rtadv,
|
||||
AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature]))
|
||||
AC_ARG_ENABLE(irdp,
|
||||
@ -392,7 +394,10 @@ AC_ARG_ENABLE([oldvpn_commands],
|
||||
AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands]))
|
||||
AC_ARG_ENABLE(rpki,
|
||||
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
|
||||
AC_ARG_ENABLE([clippy-only],
|
||||
AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
|
||||
|
||||
AS_IF([test "${enable_clippy_only}" != "yes"], [
|
||||
AC_CHECK_HEADERS(json-c/json.h)
|
||||
AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm])
|
||||
if test $ac_cv_lib_json_c_json_object_get = no; then
|
||||
@ -401,6 +406,7 @@ if test $ac_cv_lib_json_c_json_object_get = no; then
|
||||
AC_MSG_ERROR([lib json is needed to compile])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE([dev_build],
|
||||
AS_HELP_STRING([--enable-dev-build], [build for development]))
|
||||
@ -875,6 +881,7 @@ case "$host_os" in
|
||||
|
||||
AC_DEFINE(OPEN_BSD,,OpenBSD)
|
||||
AC_DEFINE(KAME,1,KAME IPv6)
|
||||
AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding)
|
||||
|
||||
if test "x${enable_pimd}" != "xno"; then
|
||||
case "$host_os" in
|
||||
@ -891,12 +898,29 @@ case "$host_os" in
|
||||
|
||||
AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST)
|
||||
AC_DEFINE(KAME,1,KAME IPv6)
|
||||
AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding)
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(SOLARIS, test "${SOLARIS}" = "solaris")
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
dnl ------------------------
|
||||
dnl Integrated REALMS option
|
||||
dnl ------------------------
|
||||
if test "${enable_realms}" = "yes"; then
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_DEFINE(SUPPORT_REALMS,, Realms support)
|
||||
;;
|
||||
*)
|
||||
echo "Sorry, only Linux has REALMS support"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AM_CONDITIONAL([SUPPORT_REALMS], [test "${enable_realms}" = "yes"])
|
||||
|
||||
dnl ---------------------
|
||||
dnl Integrated VTY option
|
||||
dnl ---------------------
|
||||
|
@ -72,7 +72,7 @@ adding a new backport.
|
||||
(see `rules` file for available options)
|
||||
|
||||
export WANT_BGP_VNC=1
|
||||
export WANT_WANT_CUMULUS_MODE=1
|
||||
export WANT_CUMULUS_MODE=1
|
||||
debuild -b -uc -us
|
||||
|
||||
DONE.
|
||||
|
@ -59,17 +59,37 @@ $(srcdir)/frr.info: $(frr_TEXINFOS) defines.texi
|
||||
frr.dvi: $(frr_TEXINFOS) defines.texi
|
||||
frr.html: $(frr_TEXINFOS) defines.texi
|
||||
|
||||
frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
|
||||
frr_TEXINFOS = \
|
||||
appendix.texi \
|
||||
basic.texi \
|
||||
bgpd.texi \
|
||||
isisd.texi \
|
||||
filter.texi \
|
||||
vnc.texi \
|
||||
babeld.texi \
|
||||
install.texi ipv6.texi kernel.texi main.texi \
|
||||
install.texi \
|
||||
ipv6.texi \
|
||||
kernel.texi \
|
||||
main.texi \
|
||||
nhrpd.texi \
|
||||
eigrpd.texi \
|
||||
ospf6d.texi ospfd.texi \
|
||||
overview.texi protocol.texi ripd.texi ripngd.texi routemap.texi \
|
||||
snmp.texi vtysh.texi routeserver.texi $(figures_png) \
|
||||
snmptrap.texi ospf_fundamentals.texi isisd.texi $(figures_txt) \
|
||||
rpki.texi
|
||||
ospf6d.texi \
|
||||
ospfd.texi \
|
||||
overview.texi \
|
||||
protocol.texi \
|
||||
ripd.texi \
|
||||
ripngd.texi \
|
||||
routemap.texi \
|
||||
snmp.texi \
|
||||
vtysh.texi \
|
||||
routeserver.texi \
|
||||
$(figures_png) \
|
||||
snmptrap.texi \
|
||||
ospf_fundamentals.texi \
|
||||
isisd.texi $(figures_txt) \
|
||||
rpki.texi \
|
||||
pimd.texi \
|
||||
#END
|
||||
|
||||
.png.eps:
|
||||
$(PNGTOEPS) $< "$@"
|
||||
|
@ -85,6 +85,10 @@ Enable Traffic Engineering Extension for ISIS (RFC5305)
|
||||
@item --enable-multipath=@var{ARG}
|
||||
Enable support for Equal Cost Multipath. @var{ARG} is the maximum number
|
||||
of ECMP paths to allow, set to 0 to allow unlimited number of paths.
|
||||
@item --enable-realms
|
||||
Enable the support of linux Realms. Convert tag values from 1-255
|
||||
into a realm value when inserting into the linux kernel. Then
|
||||
routing policy can be assigned to the realm. See the tc man page.
|
||||
@item --disable-rtadv
|
||||
Disable support IPV6 router advertisement in zebra.
|
||||
@item --enable-gcc-rdynamic
|
||||
|
366
doc/pimd.texi
Normal file
366
doc/pimd.texi
Normal file
@ -0,0 +1,366 @@
|
||||
@c -*-texinfo-*-
|
||||
@c This is part of the Frr Manual.
|
||||
@c @value{COPYRIGHT_STR}
|
||||
@c See file frr.texi for copying conditions.
|
||||
@node PIM
|
||||
@chapter PIM
|
||||
|
||||
PIM -- Protocol Independent Multicast
|
||||
|
||||
@command{pimd} supports pim-sm as well as igmp v2 and v3. pim is
|
||||
vrf aware and can work within the context of vrf's in order to
|
||||
do S,G mrouting.
|
||||
|
||||
@menu
|
||||
* Starting and Stopping pimd::
|
||||
* PIM Configuration::
|
||||
* PIM Interface Configuration::
|
||||
* PIM Multicast RIB insertion::
|
||||
* Show PIM Information::
|
||||
* PIM Debug Commands::
|
||||
@end menu
|
||||
|
||||
@node Starting and Stopping pimd
|
||||
@section Starting and Stopping pimd
|
||||
|
||||
The default configuration file name of @command{pimd}'s is
|
||||
@file{pimd.conf}. When invocation @command{pimd} searches directory
|
||||
@value{INSTALL_PREFIX_ETC}. If @file{pimd.conf} is not there
|
||||
then next search current directory.
|
||||
|
||||
@command{pimd} requires zebra for proper operation. Additionally
|
||||
@command{pimd} depends on routing properly setup and working
|
||||
in the network that it is working on.
|
||||
|
||||
@example
|
||||
@group
|
||||
# zebra -d
|
||||
# pimd -d
|
||||
@end group
|
||||
@end example
|
||||
|
||||
Please note that @command{zebra} must be invoked before @command{pimd}.
|
||||
|
||||
To stop @command{pimd}. Please use @command{kill `cat
|
||||
/var/run/pimd.pid`}. Certain signals have special meanings to @command{pimd}.
|
||||
|
||||
@table @samp
|
||||
@item SIGUSR1
|
||||
Rotate @command{pimd} logfile.
|
||||
@item SIGINT
|
||||
@itemx SIGTERM
|
||||
@command{pimd} sweeps all installed PIM mroutes then terminates properly.
|
||||
@end table
|
||||
|
||||
@command{pimd} invocation options. Common options that can be specified
|
||||
(@pxref{Common Invocation Options}).
|
||||
|
||||
@node PIM Configuration
|
||||
|
||||
@deffn Command {ip pim rp A.B.C.D A.B.C.D/M} {}
|
||||
In order to use pim, it is necessary to configure a RP for join
|
||||
messages to be sent to. Currently the only methodology to
|
||||
do this is via static rp commands. All routers in the
|
||||
pim network must agree on these values. The first ip address
|
||||
is the RP's address and the second value is the matching
|
||||
prefix of group ranges covered. This command is vrf aware,
|
||||
to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim spt-switchover infinity-and-beyond} {}
|
||||
On the last hop router if it is desired to not switch over
|
||||
to the SPT tree. Configure this command. This command is
|
||||
vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
#end deffn
|
||||
|
||||
@deffn Comand {ip pim ecmp} {}
|
||||
If pim has the a choice of ECMP nexthops for a particular
|
||||
RPF, pim will cause S,G flows to be spread out amongst
|
||||
the nexthops. If this command is not specified then
|
||||
the first nexthop found will be used. This command
|
||||
is vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim ecmp rebalance} {}
|
||||
If pim is using ECMP and an interface goes down, cause
|
||||
pim to rebalance all S,G flows aross the remaining
|
||||
nexthops. If this command is not configured pim only
|
||||
modifies those S,G flows that were using the interface
|
||||
that went down. This command is vrf aware, to configure
|
||||
for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim join-prune-interval (60-600)} {}
|
||||
Modify the join/prune interval that pim uses to the
|
||||
new value. Time is specified in seconds. This command
|
||||
is vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim keep-alive-timer (31-60000)} {}
|
||||
Modify the time out value for a S,G flow from 31-60000
|
||||
seconds. 31 seconds is choosen for a lower bound
|
||||
because some hardware platforms cannot see data flowing
|
||||
in better than 30 second chunks. This comand is vrf
|
||||
aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim packets (1-100)} {}
|
||||
When processing packets from a neighbor process the
|
||||
number of packets incoming at one time before moving
|
||||
on to the next task. The default value is 3 packets.
|
||||
This command is only useful at scale when you can
|
||||
possibly have a large number of pim control packets
|
||||
flowing. This command is vrf aware, to configure for
|
||||
a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim register-suppress-time (5-60000)} {}
|
||||
Modify the time that pim will register suppress a FHR
|
||||
will send register notifications to the kernel. This command
|
||||
is vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim send-v6-secondary} {}
|
||||
When sending pim hello packets tell pim to send
|
||||
any v6 secondary addresses on the interface. This
|
||||
information is used to allow pim to use v6 nexthops
|
||||
in it's decision for RPF lookup. This command
|
||||
is vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip pim ssm prefix-list WORD} {}
|
||||
Specify a range of group addresses via a prefix-list
|
||||
that forces pim to never do SM over. This command
|
||||
is vrf aware, to configure for a vrf, enter the vrf submode.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {ip multicast rpf-lookup-mode WORD} {}
|
||||
Modify how PIM does RPF lookups in the zebra routing table.
|
||||
You can use these choices:
|
||||
@table @lookup_modes
|
||||
@item longer-prefix
|
||||
Lookup the RPF in both tables using the longer prefix as a match
|
||||
@item lower-distance
|
||||
Lookup the RPF in both tables using the lower distance as a match
|
||||
@item mrib-only
|
||||
Lookup in the Multicast RIB only
|
||||
@item mrib-then-urib
|
||||
Lookup in the Multicast RIB then the Unicast Rib, returning first found.
|
||||
This is the default value for lookup if this command is not entered
|
||||
@item urib-only
|
||||
Lookup in the Unicast Rib only.
|
||||
@end table
|
||||
@end deffn
|
||||
|
||||
@node PIM Interface Configuration
|
||||
@section PIM Interface Configuration
|
||||
|
||||
PIM interface commands allow you to configure an
|
||||
interface as either a Receiver or a interface
|
||||
that you would like to form pim neighbors on. If the
|
||||
interface is in a vrf, enter the interface command with
|
||||
the vrf keyword at the end.
|
||||
|
||||
@deffn {PIM Interface Command] {ip pim bfd} {}
|
||||
Turns on BFD support for PIM for this interface.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip pim drpriority (1-4294967295)} {}
|
||||
Set the DR Priority for the interface. This command is useful
|
||||
to allow the user to influence what node becomes the DR for a
|
||||
lan segment.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip pim hello (1-180) (1-180)} {}
|
||||
Set the pim hello and hold interval for a interface.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip pim sm} {}
|
||||
Tell pim that we would like to use this interface to form
|
||||
pim neighbors over. Please note we will *not* accept
|
||||
igmp reports over this interface with this command.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip igmp} {}
|
||||
Tell pim to receive IGMP reports and Query on this
|
||||
interface. The default version is v3. This command
|
||||
is useful on the LHR.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip igmp query-interval (1-1800)} {}
|
||||
Set the IGMP query interval that PIM will use.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip igmp query-max-response-time (10-250)} {}
|
||||
Set the IGMP query response timeout value. If an report is not returned
|
||||
in the specified time we will assume the S,G or *,G has timed out.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip igmp version (2-3)} {}
|
||||
Set the IGMP version used on this interface. The default value
|
||||
is 3.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Interface Command} {ip multicat boundary oil WORD} {}
|
||||
Set a pim multicast boundary, based upon the WORD prefix-list. If
|
||||
a pim join or IGMP report is received on this interface and the Group
|
||||
is denyed by the prefix-list, PIM will ignore the join or report.
|
||||
@end deffn
|
||||
|
||||
@node PIM Multicast RIB insertion::
|
||||
@section PIM Multicast RIB insertion::
|
||||
|
||||
In order to influence Multicast RPF lookup, it is possible to insert
|
||||
into zebra routes for the Multicast RIB. These routes are only
|
||||
used for RPF lookup and will not be used by zebra for insertion
|
||||
into the kernel *or* for normal rib processing. As such it is
|
||||
possible to create weird states with these commands. Use with
|
||||
caution. Most of the time this will not be necessary.
|
||||
|
||||
@deffn {PIM Multicast RIB insertion} {ip mroute A.B.C.D/M A.B.C.D (1-255)} {}
|
||||
Insert into the Multicast Rib Route A.B.C.D/M with specified nexthop. The distance can be specified as well if desired.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Multicast RIB insertion} {ip mroute A.B.C.D/M INTERFACE (1-255)} {}
|
||||
Insert into the Multicast Rib Route A.B.C.D/M using the specified INTERFACE.
|
||||
The distance can be specified as well if desired.
|
||||
@end deffn
|
||||
|
||||
@node Show PIM Information::
|
||||
@section Show PIM Information
|
||||
|
||||
All PIM show commands are vrf aware and typically allow you to insert
|
||||
a specified vrf command if information is desired about a specific vrf.
|
||||
If no vrf is specified then the default vrf is assumed. Finally
|
||||
the special keyword 'all' allows you to look at all vrfs for the command.
|
||||
Naming a vrf 'all' will cause great confusion.
|
||||
|
||||
@deffn {Show PIM Information} {show ip multicast}
|
||||
Display various information about the interfaces used in this pim
|
||||
instance.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip mroute}
|
||||
Display information about installed into the kernel S,G mroutes.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip mroute count}
|
||||
Display information about installed into the kernel S,G mroutes
|
||||
and in addition display data about packet flow for the mroutes.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim assert}
|
||||
Display information about asserts in the PIM system for S,G mroutes.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim assert-internal}
|
||||
Display internal assert state for S,G mroutes
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim assert-metric}
|
||||
Display metric information about assert state for S,G mroutes
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim assert-winner-metric}
|
||||
Display winner metric for assert state for S,G mroutes
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim group-type}
|
||||
Display SSM group ranges
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim interface}
|
||||
Display information about interfaces PIM is using.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim join}
|
||||
Display information about PIM joins received.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim local-membership} {}
|
||||
Display information about PIM interface local-membership
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim neighbor} {}
|
||||
Display information about PIM neighbors
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim nexthop} {}
|
||||
Display information about pim nexthops that are being
|
||||
used
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim nexthop-lookup} {}
|
||||
Display information about a S,G pair and how the RPF would
|
||||
be choosen. This is especially useful if there are ECMP's
|
||||
available from the RPF lookup.
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim rp-info} {}
|
||||
Display information about RP's that are configured on
|
||||
this router
|
||||
@end deffn
|
||||
|
||||
@deffn {Show PIM Information} {show ip pim rpf} {}
|
||||
Display information about currently being used S,G's
|
||||
and their RPF lookup information. Additionally display
|
||||
some statistics about what has been happening on the
|
||||
router
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip pim secondary} {}
|
||||
Display information about an interface and all the
|
||||
secondary addresses associated with it
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip pim state} {}
|
||||
Display information about known S,G's and incoming
|
||||
interface as well as the OIL and how they were choosen
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip pim upstream} {}
|
||||
Display upstream information about a S,G mroute
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip pim upstream-join-desired} {}
|
||||
Display upstream information for S,G's and if we desire to
|
||||
join the mcast tree
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip pim upstream-rpf} {}
|
||||
Display upstream information for S,G's and the RPF data
|
||||
associated with them
|
||||
@end deffn
|
||||
|
||||
@deffn {show PIM Information} {show ip rpf} {}
|
||||
Display the multicast RIB created in zebra
|
||||
@end deffn
|
||||
|
||||
@node PIM Debug Commands
|
||||
@section PIM Debug Commands
|
||||
|
||||
The debugging subsystem for PIM behaves in accordance with how FRR handles debugging. You can specify debugging at the enable cli mode as well as the configure cli mode. If you specify debug commands in the configuration cli mode, the debug commands can be persistent across restarts of the FRR pimd if the config was written out.
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim events}
|
||||
This turns on debugging for PIM system events. Especially timers.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim nht}
|
||||
This turns on debugging for PIM nexthop tracking. It will display information about RPF lookups and information about when a nexthop changes.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim packet-dump}
|
||||
This turns on an extraordinary amount of data. Each pim packet sent and received is dumped for debugging purposes. This should be considered a developer only command
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim packets}
|
||||
This turns on information about packet generation for sending and about packet handling from a received packet
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim trace}
|
||||
This traces pim code and how it is running.
|
||||
@end deffn
|
||||
|
||||
@deffn {PIM Debug Commands} {debug pim zebra}
|
||||
This gathers data about events from zebra that come up through the zapi
|
||||
@end deffn
|
@ -171,6 +171,11 @@ Matches the specified @var{as_path}.
|
||||
Matches the specified @var{metric}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Route-map Command} {match tag @var{tag}} {}
|
||||
Matches the specified tag value associated with the route.
|
||||
This tag value can be in the range of (1-4294967295).
|
||||
@end deffn
|
||||
|
||||
@deffn {Route-map Command} {match local-preference @var{metric}} {}
|
||||
Matches the specified @var{local-preference}.
|
||||
@end deffn
|
||||
@ -198,6 +203,14 @@ in this manner.
|
||||
@node Route Map Set Command
|
||||
@section Route Map Set Command
|
||||
|
||||
@deffn {Route-map Command} {set tag @var{tag}} {}
|
||||
Set a tag on the matched route. This tag value can be from
|
||||
(1-4294967295). Additionally if you have compiled with
|
||||
the --enable-realms configure option. Tag values from (1-255)
|
||||
are sent to the linux kernel as a realm value. Then route
|
||||
policy can be applied. See the tc man page.
|
||||
@end deffn
|
||||
|
||||
@deffn {Route-map Command} {set ip next-hop @var{ipv4_address}} {}
|
||||
Set the BGP nexthop address.
|
||||
@end deffn
|
||||
|
@ -14,8 +14,6 @@
|
||||
* into proprietary software; there is no requirement for such software to
|
||||
* contain a copyright notice related to this source.
|
||||
*
|
||||
* $Id: dict.h,v 1.3 2005/09/25 12:04:25 hasso Exp $
|
||||
* $Name: $
|
||||
*/
|
||||
|
||||
#ifndef DICT_H
|
||||
|
@ -46,15 +46,14 @@
|
||||
#include "privs.h"
|
||||
|
||||
struct bpf_insn llcfilter[] = {
|
||||
/* check first byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN),
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS,
|
||||
ETHER_HDR_LEN), /* check first byte */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5),
|
||||
/* check second byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),
|
||||
/* check third byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1),
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0,
|
||||
3), /* check second byte */
|
||||
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2),
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */
|
||||
BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
|
||||
BPF_STMT(BPF_RET + BPF_K, 0)};
|
||||
u_int readblen = 0;
|
||||
@ -242,14 +241,15 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa)
|
||||
|
||||
assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
|
||||
|
||||
offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN;
|
||||
offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
|
||||
|
||||
/* then we lose the BPF, LLC and ethernet headers */
|
||||
stream_write(circuit->rcv_stream, readbuff + offset,
|
||||
bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN);
|
||||
bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
|
||||
stream_set_getp(circuit->rcv_stream, 0);
|
||||
|
||||
memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN);
|
||||
memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN,
|
||||
ETH_ALEN);
|
||||
|
||||
if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0)
|
||||
zlog_warn("Flushing failed: %s", safe_strerror(errno));
|
||||
@ -263,7 +263,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
|
||||
ssize_t written;
|
||||
size_t buflen;
|
||||
|
||||
buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN;
|
||||
buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN;
|
||||
if (buflen > sizeof(sock_buff)) {
|
||||
zlog_warn(
|
||||
"isis_send_pdu_bcast: sock_buff size %zu is less than "
|
||||
@ -289,12 +289,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
|
||||
/*
|
||||
* Then the LLC
|
||||
*/
|
||||
sock_buff[ETH_ALEN] = ISO_SAP;
|
||||
sock_buff[ETH_ALEN + 1] = ISO_SAP;
|
||||
sock_buff[ETH_ALEN + 2] = 0x03;
|
||||
sock_buff[ETHER_HDR_LEN] = ISO_SAP;
|
||||
sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP;
|
||||
sock_buff[ETHER_HDR_LEN + 2] = 0x03;
|
||||
|
||||
/* then we copy the data */
|
||||
memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data,
|
||||
memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data,
|
||||
stream_get_endp(circuit->snd_stream));
|
||||
|
||||
/* now we can send this */
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include "frr_pthread.h"
|
||||
#include "memory.h"
|
||||
@ -182,3 +183,8 @@ unsigned int frr_pthread_get_id()
|
||||
{
|
||||
return next_id++;
|
||||
}
|
||||
|
||||
void frr_pthread_yield(void)
|
||||
{
|
||||
(void)sched_yield();
|
||||
}
|
||||
|
@ -130,6 +130,9 @@ int frr_pthread_stop(unsigned int id, void **result);
|
||||
/* Stops all frr_pthread's. */
|
||||
void frr_pthread_stop_all(void);
|
||||
|
||||
/* Yields the current thread of execution */
|
||||
void frr_pthread_yield(void);
|
||||
|
||||
/* Returns a unique identifier for use with frr_pthread_new().
|
||||
*
|
||||
* Internally, this is an integer that increments after each call to this
|
||||
|
3
lib/if.c
3
lib/if.c
@ -663,8 +663,9 @@ DEFUN_NOSH (no_interface,
|
||||
"Interface's name\n"
|
||||
VRF_CMD_HELP_STR)
|
||||
{
|
||||
int idx_vrf = 4;
|
||||
const char *ifname = argv[2]->arg;
|
||||
const char *vrfname = (argc > 3) ? argv[3]->arg : NULL;
|
||||
const char *vrfname = (argc > 3) ? argv[idx_vrf]->arg : NULL;
|
||||
|
||||
// deleting interface
|
||||
struct interface *ifp;
|
||||
|
@ -1,7 +1,3 @@
|
||||
/* $USAGI: md5.c,v 1.2 2000/11/02 11:59:24 yoshfuji Exp $ */
|
||||
/* $KAME: md5.c,v 1.2 2000/05/27 07:07:48 jinmei Exp $ */
|
||||
/* $Id: md5.c,v 1.6 2006/01/17 23:39:04 vincent Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004 6WIND
|
||||
* <Vincent.Jardin@6WIND.com>
|
||||
|
@ -1,7 +1,3 @@
|
||||
/* $USAGI: md5.h,v 1.2 2000/11/02 11:59:25 yoshfuji Exp $ */
|
||||
/* $KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $ */
|
||||
/* $Id: md5.h,v 1.3 2006/01/17 17:40:45 paul Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004 6WIND
|
||||
* <Vincent.Jardin@6WIND.com>
|
||||
|
133
lib/ringbuf.c
Normal file
133
lib/ringbuf.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Circular buffer implementation.
|
||||
* Copyright (C) 2017 Cumulus Networks
|
||||
* Quentin Young
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <zebra.h>
|
||||
|
||||
#include "ringbuf.h"
|
||||
#include "memory.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer")
|
||||
|
||||
struct ringbuf *ringbuf_new(size_t size)
|
||||
{
|
||||
struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
|
||||
buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
|
||||
buf->size = size;
|
||||
buf->empty = true;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ringbuf_del(struct ringbuf *buf)
|
||||
{
|
||||
XFREE(MTYPE_RINGBUFFER, buf->data);
|
||||
XFREE(MTYPE_RINGBUFFER, buf);
|
||||
}
|
||||
|
||||
size_t ringbuf_remain(struct ringbuf *buf)
|
||||
{
|
||||
ssize_t diff = buf->end - buf->start;
|
||||
diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
|
||||
diff += (diff < 0) ? buf->size : 0;
|
||||
return (size_t)diff;
|
||||
}
|
||||
|
||||
size_t ringbuf_space(struct ringbuf *buf)
|
||||
{
|
||||
return buf->size - ringbuf_remain(buf);
|
||||
}
|
||||
|
||||
size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
|
||||
{
|
||||
const uint8_t *dp = data;
|
||||
size_t space = ringbuf_space(buf);
|
||||
size_t copysize = MIN(size, space);
|
||||
size_t tocopy = copysize;
|
||||
if (tocopy >= buf->size - buf->end) {
|
||||
size_t ts = buf->size - buf->end;
|
||||
memcpy(buf->data + buf->end, dp, ts);
|
||||
buf->end = 0;
|
||||
tocopy -= ts;
|
||||
dp += ts;
|
||||
}
|
||||
memcpy(buf->data + buf->end, dp, tocopy);
|
||||
buf->end += tocopy;
|
||||
buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
|
||||
return copysize;
|
||||
}
|
||||
|
||||
size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
|
||||
{
|
||||
uint8_t *dp = data;
|
||||
size_t remain = ringbuf_remain(buf);
|
||||
size_t copysize = MIN(remain, size);
|
||||
size_t tocopy = copysize;
|
||||
if (tocopy >= buf->size - buf->start) {
|
||||
size_t ts = buf->size - buf->start;
|
||||
memcpy(dp, buf->data + buf->start, ts);
|
||||
buf->start = 0;
|
||||
tocopy -= ts;
|
||||
dp += ts;
|
||||
}
|
||||
memcpy(dp, buf->data + buf->start, tocopy);
|
||||
buf->start = buf->start + tocopy;
|
||||
buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
|
||||
return copysize;
|
||||
}
|
||||
|
||||
size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
|
||||
{
|
||||
uint8_t *dp = data;
|
||||
size_t remain = ringbuf_remain(buf);
|
||||
if (offset >= remain)
|
||||
return 0;
|
||||
size_t copysize = MAX(MIN(remain - offset, size), (size_t) 0);
|
||||
size_t tocopy = copysize;
|
||||
size_t cstart = (buf->start + offset) % buf->size;
|
||||
if (tocopy >= buf->size - cstart) {
|
||||
size_t ts = buf->size - cstart;
|
||||
memcpy(dp, buf->data + cstart, ts);
|
||||
cstart = 0;
|
||||
tocopy -= ts;
|
||||
dp += ts;
|
||||
}
|
||||
memcpy(dp, buf->data + cstart, tocopy);
|
||||
return copysize;
|
||||
}
|
||||
|
||||
size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size)
|
||||
{
|
||||
size_t tocopy = MIN(ringbuf_space(to), size);
|
||||
uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy);
|
||||
tocopy = ringbuf_peek(from, 0, cbuf, tocopy);
|
||||
size_t put = ringbuf_put(to, cbuf, tocopy);
|
||||
XFREE(MTYPE_TMP, cbuf);
|
||||
return put;
|
||||
}
|
||||
|
||||
void ringbuf_reset(struct ringbuf *buf)
|
||||
{
|
||||
buf->start = buf->end = 0;
|
||||
buf->empty = true;
|
||||
}
|
||||
|
||||
void ringbuf_wipe(struct ringbuf *buf)
|
||||
{
|
||||
memset(buf->data, 0x00, buf->size);
|
||||
ringbuf_reset(buf);
|
||||
}
|
125
lib/ringbuf.h
Normal file
125
lib/ringbuf.h
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Circular buffer implementation.
|
||||
* Copyright (C) 2017 Cumulus Networks
|
||||
* Quentin Young
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _FRR_RINGBUF_H_
|
||||
#define _FRR_RINGBUF_H_
|
||||
|
||||
#include <zebra.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
struct ringbuf {
|
||||
size_t size;
|
||||
ssize_t start;
|
||||
ssize_t end;
|
||||
bool empty;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a new ring buffer.
|
||||
*
|
||||
* @param size buffer size, in bytes
|
||||
* @return the newly created buffer
|
||||
*/
|
||||
struct ringbuf *ringbuf_new(size_t size);
|
||||
|
||||
/*
|
||||
* Deletes a ring buffer and frees all associated resources.
|
||||
*
|
||||
* @param buf the ring buffer to destroy
|
||||
*/
|
||||
void ringbuf_del(struct ringbuf *buf);
|
||||
|
||||
/*
|
||||
* Get amount of data left to read from the buffer.
|
||||
*
|
||||
* @return number of readable bytes
|
||||
*/
|
||||
size_t ringbuf_remain(struct ringbuf *buf);
|
||||
|
||||
/*
|
||||
* Get amount of space left to write to the buffer
|
||||
*
|
||||
* @return number of writeable bytes
|
||||
*/
|
||||
size_t ringbuf_space(struct ringbuf *buf);
|
||||
|
||||
|
||||
/*
|
||||
* Put data into the ring buffer.
|
||||
*
|
||||
* @param data the data to put in the buffer
|
||||
* @param size how much of data to put in
|
||||
* @return number of bytes written; will be less than size if there was not
|
||||
* enough space
|
||||
*/
|
||||
size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size);
|
||||
|
||||
/*
|
||||
* Get data from the ring buffer.
|
||||
*
|
||||
* @param data where to put the data
|
||||
* @param size how much of data to get
|
||||
* @return number of bytes read into data; will be less than size if there was
|
||||
* not enough data to read
|
||||
*/
|
||||
size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size);
|
||||
|
||||
/*
|
||||
* Peek data from the ring buffer.
|
||||
*
|
||||
* @param offset where to get the data from, in bytes offset from the
|
||||
* start of the data
|
||||
* @param data where to put the data
|
||||
* @param size how much data to get
|
||||
* @return number of bytes read into data; will be less than size
|
||||
* if there was not enough data to read; will be -1 if the
|
||||
* offset exceeds the amount of data left in the ring
|
||||
* buffer
|
||||
*/
|
||||
size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data,
|
||||
size_t size);
|
||||
|
||||
/*
|
||||
* Copy data from one ringbuf to another.
|
||||
*
|
||||
* @param to destination ringbuf
|
||||
* @param from source ringbuf
|
||||
* @param size how much data to copy
|
||||
* @return amount of data copied
|
||||
*/
|
||||
size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size);
|
||||
|
||||
/*
|
||||
* Reset buffer. Does not wipe.
|
||||
*
|
||||
* @param buf
|
||||
*/
|
||||
void ringbuf_reset(struct ringbuf *buf);
|
||||
|
||||
/*
|
||||
* Reset buffer. Wipes.
|
||||
*
|
||||
* @param buf
|
||||
*/
|
||||
void ringbuf_wipe(struct ringbuf *buf);
|
||||
|
||||
#endif /* _FRR_RINGBUF_H_ */
|
@ -51,6 +51,7 @@ lib_libfrr_la_SOURCES = \
|
||||
lib/privs.c \
|
||||
lib/ptm_lib.c \
|
||||
lib/qobj.c \
|
||||
lib/ringbuf.c \
|
||||
lib/routemap.c \
|
||||
lib/sbuf.c \
|
||||
lib/sha256.c \
|
||||
@ -130,6 +131,7 @@ pkginclude_HEADERS += \
|
||||
lib/pw.h \
|
||||
lib/qobj.h \
|
||||
lib/queue.h \
|
||||
lib/ringbuf.h \
|
||||
lib/routemap.h \
|
||||
lib/sbuf.h \
|
||||
lib/sha256.h \
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: zassert.h,v 1.2 2004/12/03 18:01:04 ajs Exp $
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga is free software; you can redistribute it and/or modify it
|
||||
|
@ -369,10 +369,21 @@ static void ospf6_asbr_routemap_update(const char *mapname)
|
||||
return;
|
||||
|
||||
for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
|
||||
if (ospf6->rmap[type].name)
|
||||
if (ospf6->rmap[type].name) {
|
||||
ospf6->rmap[type].map = route_map_lookup_by_name(
|
||||
ospf6->rmap[type].name);
|
||||
else
|
||||
|
||||
if (mapname && ospf6->rmap[type].map &&
|
||||
(strcmp(ospf6->rmap[type].name, mapname) == 0)) {
|
||||
if (IS_OSPF6_DEBUG_ASBR)
|
||||
zlog_debug("%s: route-map %s update, reset redist %s",
|
||||
__PRETTY_FUNCTION__, mapname,
|
||||
ZROUTE_NAME(type));
|
||||
|
||||
ospf6_zebra_no_redistribute(type);
|
||||
ospf6_zebra_redistribute(type);
|
||||
}
|
||||
} else
|
||||
ospf6->rmap[type].map = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -914,7 +914,7 @@ static u_char *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length,
|
||||
if (len)
|
||||
id = htonl(*offset);
|
||||
offset += len;
|
||||
offsetlen -= len;
|
||||
//offsetlen -= len; // Add back in if we need it again
|
||||
|
||||
if (exact) {
|
||||
if (v->magic & OSPFv3WWASTABLE) {
|
||||
@ -1080,8 +1080,8 @@ static u_char *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
|
||||
len = (offsetlen < 1 ? 0 : 1);
|
||||
if (len)
|
||||
instid = *offset;
|
||||
offset += len;
|
||||
offsetlen -= len;
|
||||
//offset += len; // Add back in if we ever start using again
|
||||
//offsetlen -= len;
|
||||
|
||||
if (exact) {
|
||||
oi = ospf6_interface_lookup_by_ifindex(ifindex);
|
||||
@ -1241,8 +1241,8 @@ static u_char *ospfv3NbrEntry(struct variable *v, oid *name, size_t *length,
|
||||
len = (offsetlen < 1 ? 0 : 1);
|
||||
if (len)
|
||||
rtrid = htonl(*offset);
|
||||
offset += len;
|
||||
offsetlen -= len;
|
||||
//offset += len; // Add back in if we ever start looking at data
|
||||
//offsetlen -= len;
|
||||
|
||||
if (exact) {
|
||||
oi = ospf6_interface_lookup_by_ifindex(ifindex);
|
||||
|
@ -1,5 +1,3 @@
|
||||
$Id: OSPF-ALIGNMENT.txt,v 1.1 2004/11/17 17:59:52 gdt Exp $
|
||||
|
||||
Greg Troxel <gdt@ir.bbn.com>
|
||||
2004-11-17
|
||||
|
||||
|
@ -679,8 +679,9 @@ static int ospf_ase_calculate_timer(struct thread *t)
|
||||
|
||||
monotime(&stop_time);
|
||||
|
||||
zlog_info("SPF Processing Time(usecs): External Routes: %lld\n",
|
||||
(stop_time.tv_sec - start_time.tv_sec) * 1000000LL
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_info("SPF Processing Time(usecs): External Routes: %lld\n",
|
||||
(stop_time.tv_sec - start_time.tv_sec) * 1000000LL
|
||||
+ (stop_time.tv_usec - start_time.tv_usec));
|
||||
}
|
||||
return 0;
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "ospfd/ospf_lsdb.h"
|
||||
#include "ospfd/ospf_neighbor.h"
|
||||
#include "ospfd/ospf_packet.h"
|
||||
|
||||
#include "ospfd/ospf_dump.h"
|
||||
|
||||
/* Join to the OSPF ALL SPF ROUTERS multicast group. */
|
||||
int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p,
|
||||
@ -56,10 +56,11 @@ int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p,
|
||||
"on # of multicast group memberships has been exceeded?",
|
||||
top->fd, inet_ntoa(p->u.prefix4), ifindex,
|
||||
safe_strerror(errno));
|
||||
else
|
||||
zlog_debug(
|
||||
"interface %s [%u] join AllSPFRouters Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
else {
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("interface %s [%u] join AllSPFRouters Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -78,10 +79,11 @@ int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p,
|
||||
"ifindex %u, AllSPFRouters): %s",
|
||||
top->fd, inet_ntoa(p->u.prefix4), ifindex,
|
||||
safe_strerror(errno));
|
||||
else
|
||||
zlog_debug(
|
||||
"interface %s [%u] leave AllSPFRouters Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
else {
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("interface %s [%u] leave AllSPFRouters Multicast group.",
|
||||
inet_ntoa(p->u.prefix4), ifindex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -702,12 +702,12 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
|
||||
oi->ospf);
|
||||
}
|
||||
|
||||
zlog_info(
|
||||
"nsm_change_state(%s, %s -> %s): "
|
||||
"scheduling new router-LSA origination",
|
||||
inet_ntoa(nbr->router_id),
|
||||
lookup_msg(ospf_nsm_state_msg, old_state, NULL),
|
||||
lookup_msg(ospf_nsm_state_msg, state, NULL));
|
||||
if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL))
|
||||
zlog_info("%s:(%s, %s -> %s): "
|
||||
"scheduling new router-LSA origination",
|
||||
__PRETTY_FUNCTION__, inet_ntoa(nbr->router_id),
|
||||
lookup_msg(ospf_nsm_state_msg, old_state, NULL),
|
||||
lookup_msg(ospf_nsm_state_msg, state, NULL));
|
||||
|
||||
ospf_router_lsa_update_area(oi->area);
|
||||
|
||||
|
@ -1363,9 +1363,11 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
|
||||
if (IPV4_ADDR_CMP(&nbr->router_id, &oi->ospf->router_id)
|
||||
> 0) {
|
||||
/* We're Slave---obey */
|
||||
zlog_info(
|
||||
"Packet[DD]: Neighbor %s Negotiation done (Slave).",
|
||||
inet_ntoa(nbr->router_id));
|
||||
if (CHECK_FLAG(oi->ospf->config,
|
||||
OSPF_LOG_ADJACENCY_DETAIL))
|
||||
zlog_info("Packet[DD]: Neighbor %s Negotiation done (Slave).",
|
||||
inet_ntoa(nbr->router_id));
|
||||
|
||||
nbr->dd_seqnum = ntohl(dd->dd_seqnum);
|
||||
|
||||
/* Reset I/MS */
|
||||
@ -1374,10 +1376,12 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh,
|
||||
} else {
|
||||
/* We're Master, ignore the initial DBD from
|
||||
* Slave */
|
||||
zlog_info(
|
||||
"Packet[DD]: Neighbor %s: Initial DBD from Slave, "
|
||||
"ignoring.",
|
||||
inet_ntoa(nbr->router_id));
|
||||
if (CHECK_FLAG(oi->ospf->config,
|
||||
OSPF_LOG_ADJACENCY_DETAIL))
|
||||
zlog_info(
|
||||
"Packet[DD]: Neighbor %s: Initial DBD from Slave, "
|
||||
"ignoring.",
|
||||
inet_ntoa(nbr->router_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2589,8 +2589,9 @@ static void ospfTrapNbrStateChange(struct ospf_neighbor *on)
|
||||
char msgbuf[16];
|
||||
|
||||
ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf));
|
||||
zlog_info("ospfTrapNbrStateChange trap sent: %s now %s",
|
||||
inet_ntoa(on->address.u.prefix4), msgbuf);
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__,
|
||||
inet_ntoa(on->address.u.prefix4), msgbuf);
|
||||
|
||||
oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
|
||||
index[IN_ADDR_SIZE] = 0;
|
||||
@ -2646,9 +2647,10 @@ static void ospfTrapIfStateChange(struct ospf_interface *oi)
|
||||
{
|
||||
oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)];
|
||||
|
||||
zlog_info("ospfTrapIfStateChange trap sent: %s now %s",
|
||||
inet_ntoa(oi->address->u.prefix4),
|
||||
lookup_msg(ospf_ism_state_msg, oi->state, NULL));
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__,
|
||||
inet_ntoa(oi->address->u.prefix4),
|
||||
lookup_msg(ospf_ism_state_msg, oi->state, NULL));
|
||||
|
||||
oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
|
||||
index[IN_ADDR_SIZE] = 0;
|
||||
|
@ -1463,9 +1463,7 @@ void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
|
||||
}
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("SPF: calculation timer delay = %ld", delay);
|
||||
|
||||
zlog_info("SPF: Scheduled in %ld msec", delay);
|
||||
zlog_debug("SPF: calculation timer delay = %ld msec", delay);
|
||||
|
||||
ospf->t_spf_calc = NULL;
|
||||
thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay,
|
||||
|
@ -534,11 +534,11 @@ DEFUN (no_ospf_passive_interface,
|
||||
}
|
||||
|
||||
if (ospf->vrf_id != VRF_UNKNOWN)
|
||||
ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, 0);
|
||||
ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, 0);
|
||||
|
||||
if (ifp == NULL) {
|
||||
vty_out(vty, "interface %s not found.\n",
|
||||
(char *)argv[1]->arg);
|
||||
(char *)argv[2]->arg);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
@ -619,7 +619,7 @@ DEFUN (ospf_network_area,
|
||||
ret = ospf_network_set(ospf, &p, area_id, format);
|
||||
if (ret == 0) {
|
||||
vty_out(vty, "There is already same network statement.\n");
|
||||
return CMD_WARNING;
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1974,12 +1974,13 @@ DEFUN (ospf_area_authentication_message_digest,
|
||||
"Use message-digest authentication\n")
|
||||
{
|
||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
||||
int idx_ipv4_number = 1;
|
||||
int idx = 0;
|
||||
struct ospf_area *area;
|
||||
struct in_addr area_id;
|
||||
int format;
|
||||
|
||||
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg);
|
||||
argv_find(argv, argc, "area", &idx);
|
||||
VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx + 1]->arg);
|
||||
|
||||
area = ospf_area_get(ospf, area_id);
|
||||
ospf_area_display_format_set(ospf, area, format);
|
||||
|
@ -44,6 +44,7 @@
|
||||
vty_out(vty, \
|
||||
"%% You can't configure %s to backbone\n", \
|
||||
NAME); \
|
||||
return CMD_WARNING; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -1031,9 +1031,15 @@ int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
|
||||
rn = route_node_get(ospf->networks, (struct prefix *)p);
|
||||
if (rn->info) {
|
||||
/* There is already same network statement. */
|
||||
network = rn->info;
|
||||
route_unlock_node(rn);
|
||||
return 0;
|
||||
|
||||
if (IPV4_ADDR_SAME(&area_id, &network->area_id)) {
|
||||
return 1;
|
||||
} else {
|
||||
/* There is already same network statement. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rn->info = network = ospf_network_new(area_id);
|
||||
|
@ -7333,6 +7333,7 @@ static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
|
||||
{
|
||||
int result;
|
||||
struct in_addr source_addr;
|
||||
int ret = CMD_SUCCESS;
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
|
||||
result = inet_pton(AF_INET, source, &source_addr);
|
||||
@ -7347,16 +7348,19 @@ static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
|
||||
case PIM_SUCCESS:
|
||||
break;
|
||||
case PIM_IFACE_NOT_FOUND:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "Pim not enabled on this interface\n");
|
||||
break;
|
||||
case PIM_UPDATE_SOURCE_DUP:
|
||||
ret = CMD_WARNING;
|
||||
vty_out(vty, "%% Source already set to %s\n", source);
|
||||
break;
|
||||
default:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% Source set failed\n");
|
||||
}
|
||||
|
||||
return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFUN (interface_pim_use_source,
|
||||
@ -7485,6 +7489,7 @@ static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
|
||||
enum pim_msdp_err result;
|
||||
struct in_addr peer_addr;
|
||||
struct in_addr local_addr;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
result = inet_pton(AF_INET, peer, &peer_addr);
|
||||
if (result <= 0) {
|
||||
@ -7506,19 +7511,23 @@ static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
|
||||
case PIM_MSDP_ERR_NONE:
|
||||
break;
|
||||
case PIM_MSDP_ERR_OOM:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% Out of memory\n");
|
||||
break;
|
||||
case PIM_MSDP_ERR_PEER_EXISTS:
|
||||
ret = CMD_WARNING;
|
||||
vty_out(vty, "%% Peer exists\n");
|
||||
break;
|
||||
case PIM_MSDP_ERR_MAX_MESH_GROUPS:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% Only one mesh-group allowed currently\n");
|
||||
break;
|
||||
default:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% peer add failed\n");
|
||||
}
|
||||
|
||||
return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (ip_msdp_peer,
|
||||
@ -7581,6 +7590,7 @@ static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
|
||||
{
|
||||
enum pim_msdp_err result;
|
||||
struct in_addr mbr_ip;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
result = inet_pton(AF_INET, mbr, &mbr_ip);
|
||||
if (result <= 0) {
|
||||
@ -7594,19 +7604,23 @@ static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
|
||||
case PIM_MSDP_ERR_NONE:
|
||||
break;
|
||||
case PIM_MSDP_ERR_OOM:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% Out of memory\n");
|
||||
break;
|
||||
case PIM_MSDP_ERR_MG_MBR_EXISTS:
|
||||
ret = CMD_WARNING;
|
||||
vty_out(vty, "%% mesh-group member exists\n");
|
||||
break;
|
||||
case PIM_MSDP_ERR_MAX_MESH_GROUPS:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% Only one mesh-group allowed currently\n");
|
||||
break;
|
||||
default:
|
||||
ret = CMD_WARNING_CONFIG_FAILED;
|
||||
vty_out(vty, "%% member add failed\n");
|
||||
}
|
||||
|
||||
return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFUN (ip_msdp_mesh_group_member,
|
||||
|
@ -205,6 +205,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
||||
if (!pim_ifp->sec_addr_list) {
|
||||
zlog_err("%s: failure: secondary addresslist",
|
||||
__PRETTY_FUNCTION__);
|
||||
return if_list_clean(pim_ifp);
|
||||
}
|
||||
pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
|
||||
pim_ifp->sec_addr_list->cmp =
|
||||
|
@ -640,6 +640,13 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
|
||||
|
||||
ch = THREAD_ARG(t);
|
||||
|
||||
if (PIM_DEBUG_TRACE)
|
||||
zlog_debug("%s: IFCHANNEL%s %s Prune Pending Timer Popped",
|
||||
__PRETTY_FUNCTION__,
|
||||
pim_str_sg_dump(&ch->sg),
|
||||
pim_ifchannel_ifjoin_name(ch->ifjoin_state,
|
||||
ch->flags));
|
||||
|
||||
if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) {
|
||||
ifp = ch->interface;
|
||||
pim_ifp = ifp->info;
|
||||
@ -665,16 +672,19 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
|
||||
* message on RP path upon prune timer expiry.
|
||||
*/
|
||||
ch->ifjoin_state = PIM_IFJOIN_PRUNE;
|
||||
if (ch->upstream)
|
||||
if (ch->upstream) {
|
||||
struct pim_upstream *parent =
|
||||
ch->upstream->parent;
|
||||
|
||||
pim_upstream_update_join_desired(pim_ifp->pim,
|
||||
ch->upstream);
|
||||
|
||||
pim_jp_agg_single_upstream_send(&parent->rpf,
|
||||
parent,
|
||||
true);
|
||||
}
|
||||
}
|
||||
/* from here ch may have been deleted */
|
||||
} else {
|
||||
zlog_warn(
|
||||
"%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state",
|
||||
__PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg),
|
||||
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,5 +1,3 @@
|
||||
$Id: README.txt,v 1.1 2004/08/27 15:57:35 gdt Exp $
|
||||
|
||||
This directory contains files for use with the pkgsrc framework
|
||||
(http://www.pkgsrc.org) used with NetBSD and other operating systems.
|
||||
Eventually it will be hooked into automake such that they can be
|
||||
|
@ -2,8 +2,6 @@
|
||||
!
|
||||
! RIPd sample configuration file
|
||||
!
|
||||
! $Id: ripd.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
|
||||
!
|
||||
hostname ripd
|
||||
password zebra
|
||||
!
|
||||
|
@ -2,8 +2,6 @@
|
||||
!
|
||||
! RIPngd sample configuration file
|
||||
!
|
||||
! $Id: ripngd.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
|
||||
!
|
||||
hostname ripngd
|
||||
password zebra
|
||||
!
|
||||
|
18
sharpd/.gitignore
vendored
Normal file
18
sharpd/.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
tags
|
||||
TAGS
|
||||
.deps
|
||||
.nfs*
|
||||
*.lo
|
||||
*.la
|
||||
*.a
|
||||
*.libs
|
||||
.arch-inventory
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
*clippy.c
|
||||
sharpd
|
||||
sharpd.conf
|
@ -64,6 +64,7 @@ check_PROGRAMS = \
|
||||
lib/test_memory \
|
||||
lib/test_nexthop_iter \
|
||||
lib/test_privs \
|
||||
lib/test_ringbuf \
|
||||
lib/test_srcdest_table \
|
||||
lib/test_segv \
|
||||
lib/test_sig \
|
||||
@ -116,6 +117,7 @@ lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c
|
||||
lib_test_privs_SOURCES = lib/test_privs.c
|
||||
lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \
|
||||
helpers/c/prng.c
|
||||
lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
|
||||
lib_test_segv_SOURCES = lib/test_segv.c
|
||||
lib_test_sig_SOURCES = lib/test_sig.c
|
||||
lib_test_stream_SOURCES = lib/test_stream.c
|
||||
@ -156,6 +158,7 @@ lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm
|
||||
lib_test_memory_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_privs_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_segv_LDADD = $(ALL_TESTS_LDADD)
|
||||
lib_test_sig_LDADD = $(ALL_TESTS_LDADD)
|
||||
@ -196,6 +199,7 @@ EXTRA_DIST = \
|
||||
lib/cli/test_cli.py \
|
||||
lib/cli/test_cli.refout \
|
||||
lib/test_nexthop_iter.py \
|
||||
lib/test_ringbuf.py \
|
||||
lib/test_srcdest_table.py \
|
||||
lib/test_stream.py \
|
||||
lib/test_stream.refout \
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: main.c,v 1.1 2005/04/25 16:42:24 paul Exp $
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: heavy.c,v 1.3 2005/04/25 16:42:24 paul Exp $
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: heavy-thread.c,v 1.2 2005/04/25 16:42:24 paul Exp $
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga is free software; you can redistribute it and/or modify it
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: test-privs.c,v 1.1 2005/10/11 03:48:28 paul Exp $
|
||||
*
|
||||
* This file is part of Quagga.
|
||||
*
|
||||
* Quagga is free software; you can redistribute it and/or modify it
|
||||
|
190
tests/lib/test_ringbuf.c
Normal file
190
tests/lib/test_ringbuf.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Circular buffer tests.
|
||||
* Copyright (C) 2017 Cumulus Networks
|
||||
* Quentin Young
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <zebra.h>
|
||||
#include <memory.h>
|
||||
#include "ringbuf.h"
|
||||
|
||||
static void validate_state(struct ringbuf *buf, size_t size, size_t contains)
|
||||
{
|
||||
assert(buf->size == size);
|
||||
assert(ringbuf_remain(buf) == contains);
|
||||
assert(ringbuf_space(buf) == buf->size - contains);
|
||||
assert(buf->empty != (bool)contains);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ringbuf *soil = ringbuf_new(BUFSIZ);
|
||||
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
|
||||
/* verify reset functionality on clean buffer */
|
||||
printf("Validating reset on empty buffer...\n");
|
||||
ringbuf_reset(soil);
|
||||
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
|
||||
/* put one byte */
|
||||
printf("Validating write...\n");
|
||||
uint8_t walnut = 47;
|
||||
assert(ringbuf_put(soil, &walnut, sizeof(walnut)) == 1);
|
||||
|
||||
validate_state(soil, BUFSIZ, 1);
|
||||
|
||||
/* validate read limitations */
|
||||
printf("Validating read limits...\n");
|
||||
uint8_t nuts[2];
|
||||
assert(ringbuf_get(soil, &nuts, sizeof(nuts)) == 1);
|
||||
|
||||
/* reset */
|
||||
printf("Validating reset on full buffer...\n");
|
||||
ringbuf_reset(soil);
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
|
||||
/* copy stack garbage to buffer */
|
||||
printf("Validating big write...\n");
|
||||
uint8_t compost[BUFSIZ];
|
||||
assert(ringbuf_put(soil, &compost, sizeof(compost)) == BUFSIZ);
|
||||
|
||||
validate_state(soil, BUFSIZ, BUFSIZ);
|
||||
assert(soil->start == 0);
|
||||
assert(soil->end == 0);
|
||||
|
||||
/* read 15 bytes of garbage */
|
||||
printf("Validating read...\n");
|
||||
assert(ringbuf_get(soil, &compost, 15) == 15);
|
||||
|
||||
validate_state(soil, BUFSIZ, BUFSIZ - 15);
|
||||
assert(soil->start == 15);
|
||||
assert(soil->end == 0);
|
||||
|
||||
/* put another 10 bytes and validate wraparound */
|
||||
printf("Validating wraparound...\n");
|
||||
assert(ringbuf_put(soil, &compost[BUFSIZ/2], 10) == 10);
|
||||
|
||||
validate_state(soil, BUFSIZ, BUFSIZ - 15 + 10);
|
||||
assert(soil->start == 15);
|
||||
assert(soil->end == 10);
|
||||
|
||||
/* put another 15 bytes and validate state */
|
||||
printf("Validating size limits...\n");
|
||||
assert(ringbuf_put(soil, &compost, 15) == 5);
|
||||
validate_state(soil, BUFSIZ, BUFSIZ);
|
||||
|
||||
/* read entire buffer */
|
||||
printf("Validating big read...\n");
|
||||
assert(ringbuf_get(soil, &compost, BUFSIZ) == BUFSIZ);
|
||||
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
assert(soil->empty = true);
|
||||
assert(soil->start == soil->end);
|
||||
assert(soil->start == 15);
|
||||
|
||||
/* read empty buffer */
|
||||
printf("Validating empty read...\n");
|
||||
assert(ringbuf_get(soil, &compost, 1) == 0);
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
|
||||
/* reset, validate state */
|
||||
printf("Validating reset...\n");
|
||||
ringbuf_reset(soil);
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
assert(soil->start == 0);
|
||||
assert(soil->end == 0);
|
||||
|
||||
/* wipe, validate state */
|
||||
printf("Validating wipe...\n");
|
||||
memset(&compost, 0x00, sizeof(compost));
|
||||
ringbuf_wipe(soil);
|
||||
assert(memcmp(&compost, soil->data, sizeof(compost)) == 0);
|
||||
|
||||
/* validate maximum write */
|
||||
printf("Validating very big write...\n");
|
||||
const char flower[BUFSIZ * 2];
|
||||
assert(ringbuf_put(soil, &flower, sizeof(flower)) == BUFSIZ);
|
||||
|
||||
validate_state(soil, BUFSIZ, BUFSIZ);
|
||||
|
||||
/* wipe, validate state */
|
||||
printf("Validating wipe...\n");
|
||||
memset(&compost, 0x00, sizeof(compost));
|
||||
ringbuf_wipe(soil);
|
||||
assert(memcmp(&compost, soil->data, sizeof(compost)) == 0);
|
||||
|
||||
/* validate simple data encode / decode */
|
||||
const char *organ = "seed";
|
||||
printf("Encoding: '%s'\n", organ);
|
||||
assert(ringbuf_put(soil, organ, strlen(organ)) == 4);
|
||||
char water[strlen(organ) + 1];
|
||||
assert(ringbuf_get(soil, &water, strlen(organ)) == 4);
|
||||
water[strlen(organ)] = '\0';
|
||||
printf("Retrieved: '%s'\n", water);
|
||||
|
||||
validate_state(soil, BUFSIZ, 0);
|
||||
|
||||
/* validate simple data encode / decode across ring boundary */
|
||||
soil->start = soil->size - 2;
|
||||
soil->end = soil->start;
|
||||
const char *phloem = "root";
|
||||
printf("Encoding: '%s'\n", phloem);
|
||||
assert(ringbuf_put(soil, phloem, strlen(phloem)) == 4);
|
||||
char xylem[strlen(phloem) + 1];
|
||||
assert(ringbuf_get(soil, &xylem, 100) == 4);
|
||||
xylem[strlen(phloem)] = '\0';
|
||||
printf("Retrieved: '%s'\n", xylem);
|
||||
|
||||
ringbuf_wipe(soil);
|
||||
|
||||
/* validate simple data peek across ring boundary */
|
||||
soil->start = soil->size - 2;
|
||||
soil->end = soil->start;
|
||||
const char *cytoplasm = "tree";
|
||||
printf("Encoding: '%s'\n", cytoplasm);
|
||||
assert(ringbuf_put(soil, cytoplasm, strlen(cytoplasm)) == 4);
|
||||
char chloroplast[strlen(cytoplasm) + 1];
|
||||
assert(ringbuf_peek(soil, 2, &chloroplast[0], 100) == 2);
|
||||
assert(ringbuf_peek(soil, 0, &chloroplast[2], 2) == 2);
|
||||
chloroplast[strlen(cytoplasm)] = '\0';
|
||||
assert(!strcmp(chloroplast, "eetr"));
|
||||
printf("Retrieved: '%s'\n", chloroplast);
|
||||
|
||||
printf("Deleting...\n");
|
||||
ringbuf_del(soil);
|
||||
|
||||
printf("Creating new buffer...\n");
|
||||
soil = ringbuf_new(15);
|
||||
soil->start = soil->end = 7;
|
||||
|
||||
/* validate data encode of excessive data */
|
||||
const char *twenty = "vascular plants----";
|
||||
char sixteen[16];
|
||||
printf("Encoding: %s\n", twenty);
|
||||
assert(ringbuf_put(soil, twenty, strlen(twenty)) == 15);
|
||||
assert(ringbuf_get(soil, sixteen, 20));
|
||||
sixteen[15] = '\0';
|
||||
printf("Retrieved: %s\n", sixteen);
|
||||
assert(!strcmp(sixteen, "vascular plants"));
|
||||
|
||||
printf("Deleting...\n");
|
||||
ringbuf_del(soil);
|
||||
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
4
tests/lib/test_ringbuf.py
Normal file
4
tests/lib/test_ringbuf.py
Normal file
@ -0,0 +1,4 @@
|
||||
import frrtest
|
||||
|
||||
class TestRingbuf(frrtest.TestExitNonzero):
|
||||
program = './test_ringbuf'
|
@ -239,10 +239,10 @@ void connected_up(struct interface *ifp, struct connected *ifc)
|
||||
}
|
||||
|
||||
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
|
||||
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 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,
|
||||
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
|
||||
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
@ -561,33 +561,35 @@ static void if_delete_connected(struct interface *ifp)
|
||||
struct prefix cp;
|
||||
struct route_node *rn;
|
||||
struct zebra_if *zebra_if;
|
||||
struct listnode *node;
|
||||
struct listnode *last = NULL;
|
||||
|
||||
zebra_if = ifp->info;
|
||||
|
||||
if (ifp->connected) {
|
||||
struct listnode *node;
|
||||
struct listnode *last = NULL;
|
||||
if (!ifp->connected)
|
||||
return;
|
||||
|
||||
while ((node = (last ? last->next
|
||||
: listhead(ifp->connected)))) {
|
||||
ifc = listgetdata(node);
|
||||
while ((node = (last ? last->next
|
||||
: listhead(ifp->connected)))) {
|
||||
ifc = listgetdata(node);
|
||||
|
||||
cp = *CONNECTED_PREFIX(ifc);
|
||||
apply_mask(&cp);
|
||||
cp = *CONNECTED_PREFIX(ifc);
|
||||
apply_mask(&cp);
|
||||
|
||||
if (cp.family == AF_INET
|
||||
&& (rn = route_node_lookup(zebra_if->ipv4_subnets,
|
||||
&cp))) {
|
||||
struct listnode *anode;
|
||||
struct listnode *next;
|
||||
struct listnode *first;
|
||||
struct list *addr_list;
|
||||
if (cp.family == AF_INET
|
||||
&& (rn = route_node_lookup(zebra_if->ipv4_subnets,
|
||||
&cp))) {
|
||||
struct listnode *anode;
|
||||
struct listnode *next;
|
||||
struct listnode *first;
|
||||
struct list *addr_list;
|
||||
|
||||
route_unlock_node(rn);
|
||||
addr_list = (struct list *)rn->info;
|
||||
route_unlock_node(rn);
|
||||
addr_list = (struct list *)rn->info;
|
||||
|
||||
/* Remove addresses, secondaries first. */
|
||||
first = listhead(addr_list);
|
||||
/* Remove addresses, secondaries first. */
|
||||
first = listhead(addr_list);
|
||||
if (first)
|
||||
for (anode = first->next; anode || first;
|
||||
anode = next) {
|
||||
if (!anode) {
|
||||
@ -626,27 +628,26 @@ static void if_delete_connected(struct interface *ifp)
|
||||
last = node;
|
||||
}
|
||||
|
||||
/* Free chain list and respective route node. */
|
||||
list_delete_and_null(&addr_list);
|
||||
rn->info = NULL;
|
||||
route_unlock_node(rn);
|
||||
} else if (cp.family == AF_INET6) {
|
||||
connected_down(ifp, ifc);
|
||||
/* Free chain list and respective route node. */
|
||||
list_delete_and_null(&addr_list);
|
||||
rn->info = NULL;
|
||||
route_unlock_node(rn);
|
||||
} else if (cp.family == AF_INET6) {
|
||||
connected_down(ifp, ifc);
|
||||
|
||||
zebra_interface_address_delete_update(ifp, ifc);
|
||||
zebra_interface_address_delete_update(ifp, ifc);
|
||||
|
||||
UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
|
||||
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
|
||||
UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
|
||||
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
|
||||
|
||||
if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
|
||||
last = node;
|
||||
else {
|
||||
listnode_delete(ifp->connected, ifc);
|
||||
connected_free(ifc);
|
||||
}
|
||||
} else {
|
||||
if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED))
|
||||
last = node;
|
||||
else {
|
||||
listnode_delete(ifp->connected, ifc);
|
||||
connected_free(ifc);
|
||||
}
|
||||
} else {
|
||||
last = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +87,11 @@ int ipforward_off(void)
|
||||
|
||||
/* IPv6 forwarding control MIB. */
|
||||
int mib_ipv6[MIB_SIZ] = {CTL_NET, PF_INET6,
|
||||
#if defined(KAME)
|
||||
#if defined(BSD_V6_SYSCTL)
|
||||
IPPROTO_IPV6, IPV6CTL_FORWARDING
|
||||
#else /* NOT KAME */
|
||||
#else /* NOT BSD_V6_SYSCTL */
|
||||
IPPROTO_IP, IP6CTL_FORWARDING
|
||||
#endif /* KAME */
|
||||
#endif /* BSD_V6_SYSCTL */
|
||||
};
|
||||
|
||||
int ipforward_ipv6(void)
|
||||
|
@ -1050,7 +1050,7 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||
|| rtm->rtm_type == RTM_CHANGE)
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
&nh, 0, 0, 0, 0);
|
||||
&nh, 0, 0, 0, 0, 0);
|
||||
else
|
||||
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
@ -1098,7 +1098,7 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||
|| rtm->rtm_type == RTM_CHANGE)
|
||||
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
&nh, 0, 0, 0, 0);
|
||||
&nh, 0, 0, 0, 0, 0);
|
||||
else
|
||||
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
struct label_manager lbl_mgr;
|
||||
|
||||
extern struct zebra_privs_t zserv_privs;
|
||||
|
||||
DEFINE_MGROUP(LBL_MGR, "Label Manager");
|
||||
DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk");
|
||||
|
||||
@ -222,6 +224,7 @@ static void lm_zclient_init(char *lm_zserv_path)
|
||||
|
||||
/* Set default values. */
|
||||
zclient = zclient_new_notify(zebrad.master, &zclient_options_default);
|
||||
zclient->privs = &zserv_privs;
|
||||
zclient->sock = -1;
|
||||
zclient->t_connect = NULL;
|
||||
lm_zclient_connect(NULL);
|
||||
|
@ -85,8 +85,7 @@ struct route_entry {
|
||||
/* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */
|
||||
#define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2
|
||||
#define ROUTE_ENTRY_CHANGED 0x4
|
||||
#define ROUTE_ENTRY_SELECTED_FIB 0x8
|
||||
#define ROUTE_ENTRY_LABELS_CHANGED 0x10
|
||||
#define ROUTE_ENTRY_LABELS_CHANGED 0x8
|
||||
|
||||
/* Nexthop information. */
|
||||
u_char nexthop_num;
|
||||
@ -122,6 +121,8 @@ typedef struct rib_dest_t_ {
|
||||
*/
|
||||
struct route_entry *routes;
|
||||
|
||||
struct route_entry *selected_fib;
|
||||
|
||||
/*
|
||||
* Flags, see below.
|
||||
*/
|
||||
@ -296,7 +297,7 @@ extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
u_short instance, int flags, struct prefix *p,
|
||||
struct prefix_ipv6 *src_p, const struct nexthop *nh,
|
||||
u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
|
||||
uint8_t distance);
|
||||
uint8_t distance, route_tag_t tag);
|
||||
|
||||
extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *,
|
||||
struct prefix_ipv6 *src_p, struct route_entry *);
|
||||
|
@ -230,6 +230,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
int metric = 0;
|
||||
u_int32_t mtu = 0;
|
||||
uint8_t distance = 0;
|
||||
route_tag_t tag = 0;
|
||||
|
||||
void *dest = NULL;
|
||||
void *gate = NULL;
|
||||
@ -321,6 +322,11 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
if (tb[RTA_PRIORITY])
|
||||
metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
|
||||
|
||||
#if defined(SUPPORT_REALMS)
|
||||
if (tb[RTA_FLOW])
|
||||
tag = *(uint32_t *)RTA_DATA(tb[RTA_FLOW]);
|
||||
#endif
|
||||
|
||||
if (tb[RTA_METRICS]) {
|
||||
struct rtattr *mxrta[RTAX_MAX + 1];
|
||||
|
||||
@ -429,7 +435,8 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
memcpy(&nh.gate, gate, sz);
|
||||
|
||||
rib_add(afi, SAFI_UNICAST, vrf_id, proto,
|
||||
0, flags, &p, NULL, &nh, table, metric, mtu, distance);
|
||||
0, flags, &p, NULL, &nh, table, metric,
|
||||
mtu, distance, tag);
|
||||
} else {
|
||||
/* This is a multipath route */
|
||||
|
||||
@ -449,6 +456,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
|
||||
re->table = table;
|
||||
re->nexthop_num = 0;
|
||||
re->uptime = time(NULL);
|
||||
re->tag = tag;
|
||||
|
||||
for (;;) {
|
||||
if (len < (int)sizeof(*rtnh)
|
||||
@ -1310,7 +1318,10 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
||||
* by the routing protocol and for communicating with protocol peers.
|
||||
*/
|
||||
addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
|
||||
|
||||
#if defined(SUPPORT_REALMS)
|
||||
if (re->tag > 0 && re->tag <= 255)
|
||||
addattr32(&req.n, sizeof req, RTA_FLOW, re->tag);
|
||||
#endif
|
||||
/* Table corresponding to this route. */
|
||||
if (re->table < 256)
|
||||
req.r.rtm_table = re->table;
|
||||
|
@ -98,7 +98,7 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
|
||||
nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
|
||||
|
||||
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
|
||||
zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0);
|
||||
zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void route_read(struct zebra_ns *zns)
|
||||
|
@ -2,8 +2,6 @@
|
||||
!
|
||||
! zebra sample configuration file
|
||||
!
|
||||
! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
|
||||
!
|
||||
hostname Router
|
||||
password zebra
|
||||
enable password zebra
|
||||
|
@ -842,19 +842,7 @@ static inline int zfpm_encode_route(rib_dest_t *dest, struct route_entry *re,
|
||||
*/
|
||||
struct route_entry *zfpm_route_for_update(rib_dest_t *dest)
|
||||
{
|
||||
struct route_entry *re;
|
||||
|
||||
RE_DEST_FOREACH_ROUTE (dest, re) {
|
||||
if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
continue;
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have no route for this destination.
|
||||
*/
|
||||
return NULL;
|
||||
return dest->selected_fib;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -385,10 +385,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
struct prefix p;
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *match;
|
||||
struct route_entry *match = NULL;
|
||||
int resolved;
|
||||
struct nexthop *newhop;
|
||||
struct interface *ifp;
|
||||
rib_dest_t *dest;
|
||||
|
||||
if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|
||||
|| nexthop->type == NEXTHOP_TYPE_IPV6)
|
||||
@ -468,17 +469,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
&& !nh_resolve_via_default(p.family))
|
||||
return 0;
|
||||
|
||||
RNODE_FOREACH_RE (rn, match) {
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
|
||||
/* if the next hop is imported from another table, skip
|
||||
* it */
|
||||
if (match->type == ZEBRA_ROUTE_TABLE)
|
||||
continue;
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
break;
|
||||
}
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
if (dest && dest->selected_fib &&
|
||||
!CHECK_FLAG(dest->selected_fib->status,
|
||||
ROUTE_ENTRY_REMOVED) &&
|
||||
dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
|
||||
match = dest->selected_fib;
|
||||
|
||||
/* If there is no selected route or matched route is EGP, go up
|
||||
tree. */
|
||||
@ -555,7 +551,7 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
|
||||
struct prefix p;
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *match;
|
||||
struct route_entry *match = NULL;
|
||||
struct nexthop *newhop;
|
||||
|
||||
/* Lookup table. */
|
||||
@ -576,15 +572,14 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
|
||||
rn = route_node_match(table, (struct prefix *)&p);
|
||||
|
||||
while (rn) {
|
||||
rib_dest_t *dest;
|
||||
|
||||
route_unlock_node(rn);
|
||||
|
||||
/* Pick up selected route. */
|
||||
RNODE_FOREACH_RE (rn, match) {
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
break;
|
||||
}
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
if (dest && dest->selected_fib &&
|
||||
!CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
|
||||
match = dest->selected_fib;
|
||||
|
||||
/* If there is no selected route or matched route is EGP, go up
|
||||
tree. */
|
||||
@ -691,8 +686,9 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *match;
|
||||
struct route_entry *match = NULL;
|
||||
struct nexthop *nexthop;
|
||||
rib_dest_t *dest;
|
||||
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
|
||||
@ -707,13 +703,11 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
|
||||
/* Unlock node. */
|
||||
route_unlock_node(rn);
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
|
||||
RNODE_FOREACH_RE (rn, match) {
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
break;
|
||||
}
|
||||
if (dest && dest->selected_fib &&
|
||||
!CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
|
||||
match = dest->selected_fib;
|
||||
|
||||
if (!match)
|
||||
return NULL;
|
||||
@ -745,9 +739,10 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *match;
|
||||
struct route_entry *match = NULL;
|
||||
struct nexthop *nexthop;
|
||||
int nexthops_active;
|
||||
rib_dest_t *dest;
|
||||
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
|
||||
@ -763,15 +758,13 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
|
||||
|
||||
/* Unlock node. */
|
||||
route_unlock_node(rn);
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
|
||||
/* Find out if a "selected" RR for the discovered RIB entry exists ever.
|
||||
*/
|
||||
RNODE_FOREACH_RE (rn, match) {
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
break;
|
||||
}
|
||||
if (dest && dest->selected_fib &&
|
||||
!CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
|
||||
match = dest->selected_fib;
|
||||
|
||||
/* None such found :( */
|
||||
if (!match)
|
||||
@ -1119,8 +1112,9 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
|
||||
static void rib_uninstall(struct route_node *rn, struct route_entry *re)
|
||||
{
|
||||
rib_table_info_t *info = srcdest_rnode_table_info(rn);
|
||||
rib_dest_t *dest = rib_dest_from_rnode(rn);
|
||||
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
|
||||
if (dest && dest->selected_fib == re) {
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
hook_call(rib_update, rn, "rib_uninstall");
|
||||
|
||||
@ -1131,7 +1125,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
|
||||
if (zebra_rib_labeled_unicast(re))
|
||||
zebra_mpls_lsp_uninstall(info->zvrf, rn, re);
|
||||
|
||||
UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = NULL;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
|
||||
@ -1205,6 +1199,8 @@ int rib_gc_dest(struct route_node *rn)
|
||||
static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
struct route_entry *new)
|
||||
{
|
||||
rib_dest_t *dest = rib_dest_from_rnode(rn);
|
||||
|
||||
hook_call(rib_update, rn, "new route selected");
|
||||
|
||||
/* Update real nexthop. This may actually determine if nexthop is active
|
||||
@ -1214,7 +1210,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
return;
|
||||
}
|
||||
|
||||
SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = new;
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
char buf[SRCDEST2STR_BUFFER];
|
||||
srcdest_rnode2str(rn, buf, sizeof(buf));
|
||||
@ -1235,6 +1231,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
struct route_entry *old)
|
||||
{
|
||||
rib_dest_t *dest = rib_dest_from_rnode(rn);
|
||||
hook_call(rib_update, rn, "removing existing route");
|
||||
|
||||
/* Uninstall from kernel. */
|
||||
@ -1252,7 +1249,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
if (!RIB_SYSTEM_ROUTE(old))
|
||||
rib_uninstall_kernel(rn, old);
|
||||
|
||||
UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = NULL;
|
||||
|
||||
/* Update nexthop for route, reset changed flag. */
|
||||
nexthop_active_update(rn, old, 1);
|
||||
@ -1267,6 +1264,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
|
||||
struct nexthop *nexthop = NULL;
|
||||
int nh_active = 0;
|
||||
int installed = 1;
|
||||
rib_dest_t *dest = rib_dest_from_rnode(rn);
|
||||
|
||||
/*
|
||||
* We have to install or update if a new route has been selected or
|
||||
@ -1333,7 +1331,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
|
||||
|
||||
/* Update for redistribution. */
|
||||
if (installed)
|
||||
SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = new;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1368,7 +1366,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE(old))
|
||||
rib_uninstall_kernel(rn, old);
|
||||
UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@ -1396,8 +1394,6 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
|
||||
|
||||
/* Update prior route. */
|
||||
if (new != old) {
|
||||
UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
|
||||
|
||||
/* Set real nexthop. */
|
||||
nexthop_active_update(rn, old, 1);
|
||||
UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
|
||||
@ -1479,6 +1475,15 @@ static void rib_process(struct route_node *rn)
|
||||
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
|
||||
zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn);
|
||||
|
||||
/*
|
||||
* we can have rn's that have a NULL info pointer
|
||||
* (dest). As such let's not let the deref happen
|
||||
* additionally we know RNODE_FOREACH_RE_SAFE
|
||||
* will not iterate so we are ok.
|
||||
*/
|
||||
if (dest)
|
||||
old_fib = dest->selected_fib;
|
||||
|
||||
RNODE_FOREACH_RE_SAFE (rn, re, next) {
|
||||
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
|
||||
zlog_debug(
|
||||
@ -1494,11 +1499,6 @@ static void rib_process(struct route_node *rn)
|
||||
assert(old_selected == NULL);
|
||||
old_selected = re;
|
||||
}
|
||||
/* Currently in fib */
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
|
||||
assert(old_fib == NULL);
|
||||
old_fib = re;
|
||||
}
|
||||
|
||||
/* Skip deleted entries from selection */
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
|
||||
@ -2187,8 +2187,8 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *re;
|
||||
unsigned changed = 0;
|
||||
rib_dest_t *dest;
|
||||
|
||||
if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) {
|
||||
zlog_err("%s: zebra_vrf_table() returned NULL", __func__);
|
||||
@ -2202,6 +2202,7 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
/* Unlock node. */
|
||||
route_unlock_node(rn);
|
||||
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
/* Check all RE entries. In case any changes have to be done, requeue
|
||||
* the RN into RIBQ head. If the routing message about the new connected
|
||||
* route (generated by the IP address we are going to assign very soon)
|
||||
@ -2210,20 +2211,17 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
* revalidation
|
||||
* of the rest of the RE.
|
||||
*/
|
||||
RNODE_FOREACH_RE (rn, re) {
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)
|
||||
&& !RIB_SYSTEM_ROUTE(re)) {
|
||||
changed = 1;
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
zlog_debug(
|
||||
"%u:%s: freeing way for connected prefix",
|
||||
re->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)));
|
||||
route_entry_dump(&rn->p, NULL, re);
|
||||
}
|
||||
rib_uninstall(rn, re);
|
||||
if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) {
|
||||
changed = 1;
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
zlog_debug("%u:%s: freeing way for connected prefix",
|
||||
dest->selected_fib->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)));
|
||||
route_entry_dump(&rn->p, NULL, dest->selected_fib);
|
||||
}
|
||||
rib_uninstall(rn, dest->selected_fib);
|
||||
}
|
||||
if (changed)
|
||||
rib_queue_add(rn);
|
||||
@ -2330,6 +2328,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
struct route_entry *same = NULL;
|
||||
struct nexthop *rtnh;
|
||||
char buf2[INET6_ADDRSTRLEN];
|
||||
rib_dest_t *dest;
|
||||
|
||||
assert(!src_p || afi == AFI_IP6);
|
||||
|
||||
@ -2362,14 +2361,14 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
return;
|
||||
}
|
||||
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
fib = dest->selected_fib;
|
||||
|
||||
/* Lookup same type route. */
|
||||
RNODE_FOREACH_RE (rn, re) {
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
|
||||
continue;
|
||||
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
fib = re;
|
||||
|
||||
if (re->type != type)
|
||||
continue;
|
||||
if (re->instance != instance)
|
||||
@ -2432,8 +2431,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
UNSET_FLAG(rtnh->flags,
|
||||
NEXTHOP_FLAG_FIB);
|
||||
|
||||
UNSET_FLAG(fib->status,
|
||||
ROUTE_ENTRY_SELECTED_FIB);
|
||||
dest->selected_fib = NULL;
|
||||
} else {
|
||||
/* This means someone else, other than Zebra,
|
||||
* has deleted
|
||||
@ -2501,7 +2499,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
|
||||
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
int flags, struct prefix *p, struct prefix_ipv6 *src_p,
|
||||
const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
|
||||
u_int32_t mtu, uint8_t distance)
|
||||
u_int32_t mtu, uint8_t distance, route_tag_t tag)
|
||||
{
|
||||
struct route_entry *re;
|
||||
struct nexthop *nexthop;
|
||||
@ -2518,6 +2516,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
|
||||
re->vrf_id = vrf_id;
|
||||
re->nexthop_num = 0;
|
||||
re->uptime = time(NULL);
|
||||
re->tag = tag;
|
||||
|
||||
/* Add nexthop. */
|
||||
nexthop = nexthop_new();
|
||||
@ -2761,24 +2760,24 @@ void rib_close_table(struct route_table *table)
|
||||
{
|
||||
struct route_node *rn;
|
||||
rib_table_info_t *info;
|
||||
struct route_entry *re;
|
||||
rib_dest_t *dest;
|
||||
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
info = table->info;
|
||||
|
||||
for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
|
||||
RNODE_FOREACH_RE (rn, re) {
|
||||
if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
|
||||
continue;
|
||||
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
|
||||
if (dest && dest->selected_fib) {
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
hook_call(rib_update, rn, NULL);
|
||||
|
||||
if (!RIB_SYSTEM_ROUTE(re))
|
||||
rib_uninstall_kernel(rn, re);
|
||||
if (!RIB_SYSTEM_ROUTE(dest->selected_fib))
|
||||
rib_uninstall_kernel(rn, dest->selected_fib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Routing information base initialize. */
|
||||
|
@ -331,11 +331,12 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
}
|
||||
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
|
||||
rib_dest_t *dest = rib_dest_from_rnode(rn);
|
||||
|
||||
/* If there are other active nexthops, do an update. */
|
||||
if (re->nexthop_active_num > 1) {
|
||||
/* Update route in kernel if it's in fib */
|
||||
if (CHECK_FLAG(re->status,
|
||||
ROUTE_ENTRY_SELECTED_FIB))
|
||||
if (dest->selected_fib)
|
||||
rib_install_kernel(rn, re, re);
|
||||
/* Update redistribution if it's selected */
|
||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
|
||||
@ -350,8 +351,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||
p, (struct prefix *)src_p, re);
|
||||
/* Remove from kernel if fib route becomes
|
||||
* inactive */
|
||||
if (CHECK_FLAG(re->status,
|
||||
ROUTE_ENTRY_SELECTED_FIB))
|
||||
if (dest->selected_fib)
|
||||
rib_uninstall_kernel(rn, re);
|
||||
}
|
||||
}
|
||||
|
@ -483,8 +483,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||
vty_out(vty, "\"");
|
||||
vty_out(vty, ", distance %u, metric %u", re->distance,
|
||||
re->metric);
|
||||
if (re->tag)
|
||||
if (re->tag) {
|
||||
vty_out(vty, ", tag %u", re->tag);
|
||||
#if defined(SUPPORT_REALMS)
|
||||
if (re->tag > 0 && re->tag <= 255)
|
||||
vty_out(vty, "(realm)");
|
||||
#endif
|
||||
}
|
||||
if (re->mtu)
|
||||
vty_out(vty, ", mtu %u", re->mtu);
|
||||
if (re->vrf_id != VRF_DEFAULT) {
|
||||
@ -972,6 +977,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
|
||||
u_short ospf_instance_id)
|
||||
{
|
||||
struct route_table *table;
|
||||
rib_dest_t *dest;
|
||||
struct route_node *rn;
|
||||
struct route_entry *re;
|
||||
int first = 1;
|
||||
@ -1009,10 +1015,11 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
|
||||
|
||||
/* Show all routes. */
|
||||
for (rn = route_top(table); rn; rn = route_next(rn)) {
|
||||
dest = rib_dest_from_rnode(rn);
|
||||
|
||||
RNODE_FOREACH_RE (rn, re) {
|
||||
if (use_fib
|
||||
&& !CHECK_FLAG(re->status,
|
||||
ROUTE_ENTRY_SELECTED_FIB))
|
||||
&& re != dest->selected_fib)
|
||||
continue;
|
||||
|
||||
if (tag && re->tag != tag)
|
||||
|
Loading…
Reference in New Issue
Block a user