Merge branch 'master' into evpn-symmetric-routing

This commit is contained in:
Mitesh Kanjariya 2018-01-11 09:00:23 -08:00 committed by GitHub
commit 9bb77a5b3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 1611 additions and 987 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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];

View File

@ -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);

View File

@ -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

View File

@ -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.
*

View File

@ -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(

View File

@ -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);

View File

@ -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];

View File

@ -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) {

View File

@ -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],

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 ---------------------

View File

@ -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.

View File

@ -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) $< "$@"

View File

@ -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
View 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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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();
}

View File

@ -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

View File

@ -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;

View File

@ -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>

View File

@ -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
View 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
View 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_ */

View File

@ -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 \

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -44,6 +44,7 @@
vty_out(vty, \
"%% You can't configure %s to backbone\n", \
NAME); \
return CMD_WARNING; \
} \
}

View File

@ -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);

View File

@ -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,

View File

@ -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 =

View File

@ -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;

View File

@ -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

View File

@ -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
!

View File

@ -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
View 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

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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;
}

View File

@ -0,0 +1,4 @@
import frrtest
class TestRingbuf(frrtest.TestExitNonzero):
program = './test_ringbuf'

View File

@ -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];

View File

@ -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;
}
}
}

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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 *);

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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;
}
/*

View File

@ -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. */

View File

@ -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);
}
}

View File

@ -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)