indent:
tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux`
+
+if HAVE_GCOV
+
+coverage: check
+ @ find . -name '*.o' -exec gcov {} \;
+
+yorn:
+ @ echo "OK to upload coverage to https://coverage.io [y/N]:"
+ @ read yn; test "$$yn" = "y"
+
+upload-check-coverage:
+ @ if [ "x${COMMIT}" = "x" ]; then echo "COMMIT required"; exit 1; fi
+ @ if [ "x${TOKEN}" = "x" ]; then echo "TOKEN required"; exit 1; fi
+ curl -s https://codecov.io/bash | bash -s - -C ${COMMIT} -t ${TOKEN}
+
+force-check-coverage: coverage upload-check-coverage
+
+check-coverage: coverage yorn upload-check-coverage
+
+endif
struct peer_group
struct bgp_notify: (in-core representation of wire format?)
struct bgp_nexthop: (v4 and v6 addresses, *ifp)
- struct bgp_rd: router distinguisher: 8 octects
struct bgp_filter: distribute, prefix, aslist, route_maps
struct peer: neighbor structure (very rich/complex)
struct bgp_nlri: reference to wire format
/* Delete community-list entry from the list. */
static void community_list_entry_delete(struct community_list *list,
- struct community_entry *entry,
- int style)
+ struct community_entry *entry)
{
if (entry->next)
entry->next->prev = entry->prev;
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry, style);
+ community_list_entry_delete(list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0;
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry, style);
+ community_list_entry_delete(list, entry);
return 0;
}
if (str == NULL)
return COMMUNITY_LIST_ERR_MALFORMED_VAL;
- entry = NULL;
-
/* Get community list. */
list = community_list_get(ch, name, EXTCOMMUNITY_LIST_MASTER);
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry, style);
+ community_list_entry_delete(list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0;
if ((*ecom)->str)
XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
XFREE(MTYPE_ECOMMUNITY, *ecom);
- ecom = NULL;
}
static void ecommunity_hash_free(struct ecommunity *ecom)
int addpath_encoded;
int psize = 0;
uint8_t rtype;
- uint8_t rlen;
struct prefix p;
/* Start processing the NLRI - there may be multiple in the MP_REACH */
return -1;
rtype = *pnt++;
- psize = rlen = *pnt++;
+ psize = *pnt++;
/* When packet overflow occur return immediately. */
if (pnt + psize > lim)
struct bgpevpn *vpn = NULL;
as_t as = 0;
- /* get the default instamce - required to get the AS number for VRF
+ /* get the default instance - required to get the AS number for VRF
* auto-creatio
*/
bgp_def = bgp_get_default();
return -1;
}
- /* unimport remote routes from VRF, if it is AUTO vrf bgp_delete will
- * take care of uninstalling the routes from zebra
+ /* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured,
+ * bgp_delete would not remove/decrement bgp_info of the ip_prefix
+ * routes. This will uninstalling the routes from zebra and decremnt the
+ * bgp info count.
*/
- if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO))
- uninstall_routes_for_vrf(bgp_vrf);
+ uninstall_routes_for_vrf(bgp_vrf);
/* delete/withdraw all type-5 routes */
delete_withdraw_vrf_routes(bgp_vrf);
afi_t afi;
safi_t safi;
int psize = 0;
- uint8_t rlen;
struct prefix p;
int ret;
void *temp;
if (pnt + 1 > lim)
return -1;
- psize = rlen = *pnt++;
+ psize = *pnt++;
/* When packet overflow occur return immediately. */
if (pnt + psize > lim) {
else
json_nlri_path = json_paths;
}
- if (display == NLRI_STRING_FORMAT_LARGE)
+ if (display == NLRI_STRING_FORMAT_LARGE && binfo)
vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
binfo->flags);
bgp_fs_nlri_get_string((unsigned char *)
memset(&p, 0, sizeof(struct prefix));
p.family = stream_getw(s);
p.prefixlen = stream_getc(s);
- stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
+ stream_get(p.u.val, s, PSIZE(p.prefixlen));
label = stream_getl(s);
/* hack for the bgp instance & SAFI = have to send/receive it */
if ((*lcom)->str)
XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
XFREE(MTYPE_LCOMMUNITY, *lcom);
- lcom = NULL;
}
static void lcommunity_hash_free(struct lcommunity *lcom)
p.prefixlen =
prefixlen
- VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */
- memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
+ memcpy(p.u.val, pnt + VPN_PREFIXLEN_MIN_BYTES,
psize - VPN_PREFIXLEN_MIN_BYTES);
if (attr) {
* (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
* Using a loop here supports more complex intra-bgp import-export
* schemes that could be implemented in the future.
- *
+ *
*/
for (bi_ultimate = source_bi;
bi_ultimate->extra && bi_ultimate->extra->parent;
struct bgp_node *prn;
safi_t safi = SAFI_MPLS_VPN;
- if (!bgp_vpn)
- return;
+ assert(bgp_vpn);
/*
* Walk vpn table
}
return VRF_UNKNOWN;
}
+
+/*
+ * The purpose of this function is to process leaks that were deferred
+ * from earlier per-vrf configuration due to not-yet-existing default
+ * vrf, in other words, configuration such as:
+ *
+ * router bgp MMM vrf FOO
+ * address-family ipv4 unicast
+ * rd vpn export 1:1
+ * exit-address-family
+ *
+ * router bgp NNN
+ * ...
+ *
+ * This function gets called when the default instance ("router bgp NNN")
+ * is created.
+ */
+void vpn_leak_postchange_all(void)
+{
+ struct listnode *next;
+ struct bgp *bgp;
+ struct bgp *bgp_default = bgp_get_default();
+
+ assert(bgp_default);
+
+ /* First, do any exporting from VRFs to the single VPN RIB */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
+
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ vpn_leak_postchange(
+ BGP_VPN_POLICY_DIR_TOVPN,
+ AFI_IP,
+ bgp_default,
+ bgp);
+
+ vpn_leak_postchange(
+ BGP_VPN_POLICY_DIR_TOVPN,
+ AFI_IP6,
+ bgp_default,
+ bgp);
+ }
+
+ /* Now, do any importing to VRFs from the single VPN RIB */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
+
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ vpn_leak_postchange(
+ BGP_VPN_POLICY_DIR_FROMVPN,
+ AFI_IP,
+ bgp_default,
+ bgp);
+
+ vpn_leak_postchange(
+ BGP_VPN_POLICY_DIR_FROMVPN,
+ AFI_IP6,
+ bgp_default,
+ bgp);
+ }
+}
afi_t afi, struct bgp *bgp_vpn,
struct bgp *bgp_vrf)
{
+ /* Detect when default bgp instance is not (yet) defined by config */
+ if (!bgp_vpn)
+ return;
+
if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
afi_t afi, struct bgp *bgp_vpn,
struct bgp *bgp_vrf)
{
+ /* Detect when default bgp instance is not (yet) defined by config */
+ if (!bgp_vpn)
+ return;
+
if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
+extern void vpn_leak_postchange_all(void);
+
#endif /* _QUAGGA_BGP_MPLSVPN_H */
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
- rn2 = NULL;
-
bgp = SUBGRP_INST(subgrp);
rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
if (!rn1)
uint8_t safi; /* iana_safi_t */
};
-struct capability_as4 {
- uint32_t as4;
-};
-
struct graceful_restart_af {
afi_t afi;
safi_t safi;
uint8_t flag;
};
-struct capability_gr {
- uint16_t restart_flag_time;
- struct graceful_restart_af gr[];
-};
-
/* Capability Code */
#define CAPABILITY_CODE_MP 1 /* Multiprotocol Extensions */
#define CAPABILITY_CODE_REFRESH 2 /* Route Refresh Capability */
void *valmask, uint8_t type_entry)
{
bool ret;
- uint8_t unary_operator_val = unary_operator;
+ uint8_t unary_operator_val;
bool double_check = false;
if ((unary_operator & OPERATOR_UNARY_OR) &&
uint16_t value;
uint8_t compare_operator;
uint8_t unary_operator;
-} bgp_pbr_value_t;
+};
#define FRAGMENT_DONT 1
#define FRAGMENT_IS 2
#define FRAGMENT_FIRST 4
#define FRAGMENT_LAST 8
-struct bgp_pbr_fragment_val {
- uint8_t bitmask;
-};
-
struct bgp_pbr_entry_action {
/* used to store enum bgp_pbr_action_enum enumerate */
uint8_t action;
static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
afi_t afi, safi_t safi)
{
- struct prefix *p = &rn->p;
struct bgp_info *new_select;
struct bgp_info *old_select;
struct bgp_info_pair old_and_new;
return;
}
+ struct prefix *p = &rn->p;
+
debug = bgp_debug_bestpath(&rn->p);
if (debug) {
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
struct peer *peer, afi_t afi, safi_t safi,
struct prefix_rd *prd)
{
- int status = BGP_DAMP_NONE;
-
/* apply dampening, if result is suppressed, we'll be retaining
* the bgp_info in the RIB for historical reference.
*/
if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP)
- if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0))
+ if ((bgp_damp_withdraw(ri, rn, afi, safi, 0))
== BGP_DAMP_SUPPRESSED) {
bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi,
safi);
}
/* Fetch prefix from NLRI packet. */
- memcpy(&p.u.prefix, pnt, psize);
+ memcpy(p.u.val, pnt, psize);
/* Check address. */
if (afi == AFI_IP && safi == SAFI_UNICAST) {
bgp_info->attr->nexthop = *rins->address;
SET_FLAG(bgp_info->attr->rmap_change_flags,
BATTR_RMAP_IPV4_NHOP_CHANGED);
+ /* case for MP-BGP : MPLS VPN */
+ bgp_info->attr->mp_nexthop_global_in = *rins->address;
+ bgp_info->attr->mp_nexthop_len = sizeof(*rins->address);
}
}
* Berlin
* Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
* Hamburg
- * Copyright (C) 2017 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW
- * Hamburg
+ * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de),
+ * for HAW Hamburg
*
* This file is part of FRRouting.
*
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_route.h"
+#include "lib/thread.h"
#include "rtrlib/rtrlib.h"
#include "rtrlib/rtr_mgr.h"
#include "rtrlib/lib/ip.h"
static route_map_result_t route_match(void *rule, struct prefix *prefix,
route_map_object_t type, void *object);
static void *route_match_compile(const char *arg);
+static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
+ safi_t safi);
static struct rtr_mgr_config *rtr_config;
static struct list *cache_list;
static int rtr_is_running;
+static int rtr_is_stopping;
+static int rtr_is_starting;
static int rpki_debug;
static unsigned int polling_period;
static unsigned int expire_interval;
static unsigned int retry_interval;
static unsigned int timeout;
static unsigned int initial_synchronisation_timeout;
+static int rpki_sync_socket_rtr;
+static int rpki_sync_socket_bgpd;
static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
static struct route_map_rule_cmd route_match_rpki_cmd = {
static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
struct prefix *prefix);
+static void ipv6_addr_to_network_byte_order(const uint32_t *src, uint32_t *dest)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ dest[i] = htonl(src[i]);
+}
+
+static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ dest[i] = ntohl(src[i]);
+}
+
static route_map_result_t route_match(void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
return rtr_is_running;
}
+static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
+{
+ struct prefix *prefix = prefix_new();
+
+ prefix->prefixlen = record->min_len;
+
+ if (record->prefix.ver == LRTR_IPV4) {
+ prefix->family = AF_INET;
+ prefix->u.prefix4.s_addr = htonl(record->prefix.u.addr4.addr);
+ } else {
+ prefix->family = AF_INET6;
+ ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr,
+ prefix->u.prefix6.s6_addr32);
+ }
+
+ return prefix;
+}
+
+static int bgpd_sync_callback(struct thread *thread)
+{
+ struct bgp *bgp;
+ struct listnode *node;
+ struct prefix *prefix;
+ struct pfx_record rec;
+
+ thread_add_read(bm->master, bgpd_sync_callback, NULL,
+ rpki_sync_socket_bgpd, NULL);
+ int retval =
+ read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ if (retval != sizeof(struct pfx_record)) {
+ RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
+ return retval;
+ }
+ prefix = pfx_record_to_prefix(&rec);
+
+ afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ safi_t safi;
+
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ if (!bgp->rib[afi][safi])
+ continue;
+
+ struct list *matches = list_new();
+
+ matches->del = (void (*)(void *))bgp_unlock_node;
+
+ bgp_table_range_lookup(bgp->rib[afi][safi], prefix,
+ rec.max_len, matches);
+
+
+ struct bgp_node *bgp_node;
+
+ for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node))
+ revalidate_bgp_node(bgp_node, afi, safi);
+
+ list_delete_and_null(&matches);
+ }
+ }
+
+ prefix_free(prefix);
+ return 0;
+}
+
+static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
+ safi_t safi)
+{
+ struct bgp_adj_in *ain;
+
+ for (ain = bgp_node->adj_in; ain; ain = ain->next) {
+ int ret;
+ struct bgp_info *bgp_info = bgp_node->info;
+ mpls_label_t *label = NULL;
+ uint32_t num_labels = 0;
+
+ if (bgp_info && bgp_info->extra) {
+ label = bgp_info->extra->label;
+ num_labels = bgp_info->extra->num_labels;
+ }
+ ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi,
+ safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ label, num_labels, 1, NULL);
+
+ if (ret < 0) {
+ bgp_unlock_node(bgp_node);
+ return;
+ }
+ }
+}
+
+static void revalidate_all_routes(void)
+{
+ struct bgp *bgp;
+ struct listnode *node;
+ struct bgp_node *bgp_node;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ for (size_t i = 0; i < 2; i++) {
+ safi_t safi;
+ afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
+
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ if (!bgp->rib[afi][safi])
+ continue;
+
+ for (bgp_node =
+ bgp_table_top(bgp->rib[afi][safi]);
+ bgp_node;
+ bgp_node = bgp_route_next(bgp_node)) {
+ if (bgp_node->info != NULL) {
+ revalidate_bgp_node(bgp_node,
+ afi, safi);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
+ const struct pfx_record rec,
+ const bool added __attribute__((unused)))
+{
+ if (rtr_is_stopping || rtr_is_starting)
+ return;
+
+ int retval =
+ write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
+ if (retval != sizeof(struct pfx_record))
+ RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
+}
+
+static void rpki_init_sync_socket(void)
+{
+ int fds[2];
+
+ RPKI_DEBUG("initializing sync socket");
+ if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
+ RPKI_DEBUG("Could not open rpki sync socket");
+ return;
+ }
+ rpki_sync_socket_rtr = fds[0];
+ rpki_sync_socket_bgpd = fds[1];
+ thread_add_read(bm->master, bgpd_sync_callback, NULL,
+ rpki_sync_socket_bgpd, NULL);
+}
+
static int bgp_rpki_init(struct thread_master *master)
{
rpki_debug = 0;
rtr_is_running = 0;
+ rtr_is_stopping = 0;
cache_list = list_new();
cache_list->del = (void (*)(void *)) & free_cache;
initial_synchronisation_timeout =
INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT;
install_cli_commands();
+ rpki_init_sync_socket();
return 0;
}
stop();
list_delete_and_null(&cache_list);
+ close(rpki_sync_socket_rtr);
+ close(rpki_sync_socket_bgpd);
+
return 0;
}
unsigned int waiting_time = 0;
int ret;
+ rtr_is_stopping = 0;
+ rtr_is_starting = 1;
+
if (list_isempty(cache_list)) {
RPKI_DEBUG(
"No caches were found in config. Prefix validation is off.");
int groups_len = listcount(cache_list);
struct rtr_mgr_group *groups = get_groups();
+ RPKI_DEBUG("Polling period: %d", polling_period);
ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
- expire_interval, retry_interval, NULL, NULL, NULL,
- NULL);
+ expire_interval, retry_interval,
+ rpki_update_cb_sync_rtr, NULL, NULL, NULL);
if (ret == RTR_ERROR) {
RPKI_DEBUG("Init rtr_mgr failed.");
return ERROR;
}
if (rtr_mgr_conf_in_sync(rtr_config)) {
RPKI_DEBUG("Got synchronisation with at least one RPKI cache!");
+ RPKI_DEBUG("Forcing revalidation.");
+ rtr_is_starting = 0;
+ revalidate_all_routes();
} else {
RPKI_DEBUG(
"Timeout expired! Proceeding without RPKI validation data.");
+ rtr_is_starting = 0;
}
XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
static void stop(void)
{
+ rtr_is_stopping = 1;
if (rtr_is_running) {
rtr_mgr_stop(rtr_config);
rtr_mgr_free(rtr_config);
ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
break;
-#ifdef HAVE_IPV6
case AF_INET6:
ip_addr_prefix.ver = LRTR_IPV6;
ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
ip_addr_prefix.u.addr6.addr);
break;
-#endif /* HAVE_IPV6 */
default:
return 0;
"Preference of the cache server\n"
"Preference value\n")
{
- int return_value = SUCCESS;
+ int return_value;
// use ssh connection
if (ssh_uname) {
add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
ssh_pubkey, server_pubkey, preference);
#else
+ return_value = SUCCESS;
vty_out(vty,
"ssh sockets are not supported. "
"Please recompile rtrlib and frr with ssh support. "
return rt;
}
+
+static struct bgp_node *
+bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit,
+ const uint8_t maxlen)
+{
+ if (node->l_left && node->p.prefixlen < maxlen
+ && node->l_left->p.prefixlen <= maxlen) {
+ return bgp_node_from_rnode(node->l_left);
+ }
+ if (node->l_right && node->p.prefixlen < maxlen
+ && node->l_right->p.prefixlen <= maxlen) {
+ return bgp_node_from_rnode(node->l_right);
+ }
+
+ while (node->parent && node != limit) {
+ if (bgp_node_from_rnode(node->parent->l_left) == node
+ && node->parent->l_right) {
+ return bgp_node_from_rnode(node->parent->l_right);
+ }
+ node = bgp_node_from_rnode(node->parent);
+ }
+ return NULL;
+}
+
+void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+ uint8_t maxlen, struct list *matches)
+{
+ struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
+ struct bgp_node *matched = NULL;
+
+ if (node == NULL)
+ return;
+
+ while (node && node->p.prefixlen <= p->prefixlen
+ && prefix_match(&node->p, p)) {
+ if (node->info && node->p.prefixlen == p->prefixlen) {
+ matched = node;
+ break;
+ }
+ node = bgp_node_from_rnode(node->link[prefix_bit(
+ &p->u.prefix, node->p.prefixlen)]);
+ }
+
+ if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent)
+ return;
+ else if (matched == NULL)
+ matched = node = bgp_node_from_rnode(node->parent);
+
+ if (matched->info) {
+ bgp_lock_node(matched);
+ listnode_add(matches, matched);
+ }
+
+ while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) {
+ if (prefix_match(p, &node->p)) {
+ if (node->info) {
+ bgp_lock_node(node);
+ listnode_add(matches, node);
+ }
+ }
+ }
+}
#include "mpls.h"
#include "table.h"
#include "queue.h"
+#include "linklist.h"
struct bgp_table {
/* table belongs to this instance */
return table->version;
}
+void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+ uint8_t maxlen, struct list *matches);
+
#endif /* _QUAGGA_BGP_TABLE_H */
BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */
} bgp_vnc_subtlv_types;
-/*
- * VNC Attribute subtlvs
- */
-struct bgp_vnc_subtlv_lifetime {
- uint32_t lifetime;
-};
-
-struct bgp_vnc_subtlv_unaddr {
- struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */
-};
-
#endif /* ENABLE_BGP_VNC */
#endif /* _QUAGGA_BGP_VNC_TYPES_H */
return CMD_WARNING_CONFIG_FAILED;
}
+ /*
+ * If we just instantiated the default instance, complete
+ * any pending VRF-VPN leaking that was configured via
+ * earlier "router bgp X vrf FOO" blocks.
+ */
+ if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ vpn_leak_postchange_all();
+
/* Pending: handle when user tries to change a view to vrf n vv.
*/
}
struct peer *peer;
struct peer_group *group;
- peer = NULL;
-
ret = str2sockunion(argv[idx_peer]->arg, &su);
if (ret < 0) {
peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg);
mpls_label_t label;
int nh_othervrf = 0;
char buf_prefix[PREFIX_STRLEN]; /* filled in if we are debugging */
- bool is_evpn = false;
+ bool is_evpn;
int nh_updated;
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
}
}
-/* Reset all address family specific configuration. */
-static void peer_af_flag_reset(struct peer *peer, afi_t afi, safi_t safi)
-{
- int i;
- struct bgp_filter *filter;
- char orf_name[BUFSIZ];
-
- filter = &peer->filter[afi][safi];
-
- /* Clear neighbor filter and route-map */
- for (i = FILTER_IN; i < FILTER_MAX; i++) {
- if (filter->dlist[i].name) {
- XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name);
- filter->dlist[i].name = NULL;
- }
- if (filter->plist[i].name) {
- XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name);
- filter->plist[i].name = NULL;
- }
- if (filter->aslist[i].name) {
- XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name);
- filter->aslist[i].name = NULL;
- }
- }
- for (i = RMAP_IN; i < RMAP_MAX; i++) {
- if (filter->map[i].name) {
- XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name);
- filter->map[i].name = NULL;
- }
- }
-
- /* Clear unsuppress map. */
- if (filter->usmap.name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
- filter->usmap.name = NULL;
- filter->usmap.map = NULL;
-
- /* Clear neighbor's all address family flags. */
- peer->af_flags[afi][safi] = 0;
-
- /* Clear neighbor's all address family sflags. */
- peer->af_sflags[afi][safi] = 0;
-
- /* Clear neighbor's all address family capabilities. */
- peer->af_cap[afi][safi] = 0;
-
- /* Clear ORF info */
- peer->orf_plist[afi][safi] = NULL;
- sprintf(orf_name, "%s.%d.%d", peer->host, afi, safi);
- prefix_bgp_orf_remove_all(afi, orf_name);
-
- /* Set default neighbor send-community. */
- if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_SEND_EXT_COMMUNITY);
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_SEND_LARGE_COMMUNITY);
-
- SET_FLAG(peer->af_flags_invert[afi][safi],
- PEER_FLAG_SEND_COMMUNITY);
- SET_FLAG(peer->af_flags_invert[afi][safi],
- PEER_FLAG_SEND_EXT_COMMUNITY);
- SET_FLAG(peer->af_flags_invert[afi][safi],
- PEER_FLAG_SEND_LARGE_COMMUNITY);
- }
-
- /* Clear neighbor default_originate_rmap */
- if (peer->default_rmap[afi][safi].name)
- XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
- peer->default_rmap[afi][safi].name = NULL;
- peer->default_rmap[afi][safi].map = NULL;
-
- /* Clear neighbor maximum-prefix */
- peer->pmax[afi][safi] = 0;
- peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
-}
-
-/* peer global config reset */
-static void peer_global_config_reset(struct peer *peer)
-{
- int saved_flags = 0;
-
- peer->change_local_as = 0;
- peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1);
- if (peer->update_source) {
- sockunion_free(peer->update_source);
- peer->update_source = NULL;
- }
- if (peer->update_if) {
- XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
- peer->update_if = NULL;
- }
-
- if (peer_sort(peer) == BGP_PEER_IBGP)
- peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
- else
- peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
-
- /* These are per-peer specific flags and so we must preserve them */
- saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
- saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN);
- peer->flags = 0;
- SET_FLAG(peer->flags, saved_flags);
-
- peer->holdtime = 0;
- peer->keepalive = 0;
- peer->connect = 0;
- peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
-
- /* Reset some other configs back to defaults. */
- peer->v_start = BGP_INIT_START_TIMER;
- peer->password = NULL;
- peer->local_id = peer->bgp->router_id;
- peer->v_holdtime = peer->bgp->default_holdtime;
- peer->v_keepalive = peer->bgp->default_keepalive;
-
- bfd_info_free(&(peer->bfd_info));
-
- /* Set back the CONFIG_NODE flag. */
- SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
-}
-
/* Check peer's AS number and determines if this peer is IBGP or EBGP */
static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer)
{
else if (peer->as_type == AS_EXTERNAL)
return BGP_PEER_EBGP;
- else if (peer->as_type == AS_SPECIFIED && peer->as)
+ else if (peer->as_type == AS_SPECIFIED && peer->as) {
+ assert(bgp);
return (bgp->as == peer->as ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
+ }
else {
struct peer *peer1;
return 0;
}
-int peer_group_unbind(struct bgp *bgp, struct peer *peer,
- struct peer_group *group)
-{
- struct peer *other;
- afi_t afi;
- safi_t safi;
-
- if (group != peer->group)
- return BGP_ERR_PEER_GROUP_MISMATCH;
-
- FOREACH_AFI_SAFI (afi, safi) {
- if (peer->afc[afi][safi]) {
- peer->afc[afi][safi] = 0;
- peer_af_flag_reset(peer, afi, safi);
-
- if (peer_af_delete(peer, afi, safi) != 0) {
- zlog_err(
- "couldn't delete af structure for peer %s",
- peer->host);
- }
- }
- }
-
- assert(listnode_lookup(group->peer, peer));
- peer_unlock(peer); /* peer group list reference */
- listnode_delete(group->peer, peer);
- peer->group = NULL;
- other = peer->doppelganger;
-
- if (group->conf->as) {
- peer_delete(peer);
- if (other && other->status != Deleted) {
- if (other->group) {
- peer_unlock(other);
- listnode_delete(group->peer, other);
- }
- other->group = NULL;
- peer_delete(other);
- }
- return 0;
- }
-
- bgp_bfd_deregister_peer(peer);
- peer_global_config_reset(peer);
-
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
- peer->last_reset = PEER_DOWN_RMAP_UNBIND;
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
- bgp_session_reset(peer);
-
- return 0;
-}
-
static int bgp_startup_timer_expire(struct thread *thread)
{
struct bgp *bgp;
/* Action when the flag is changed. */
enum peer_change_type type;
-
- /* Peer down cause */
- uint8_t peer_down;
};
static const struct peer_flag_action peer_flag_action_list[] = {
vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
bgp->default_subgroup_pkt_queue_max);
- /* BGP default autoshutdown neighbors */
- if (bgp->autoshutdown)
- vty_out(vty, " bgp default shutdown\n");
-
/* BGP client-to-client reflection. */
if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
vty_out(vty, " no bgp client-to-client reflection\n");
/* listen range and limit for dynamic BGP neighbors */
bgp_config_write_listen(vty, bgp);
+ /*
+ * BGP default autoshutdown neighbors
+ *
+ * This must be placed after any peer and peer-group
+ * configuration, to avoid setting all peers to shutdown after
+ * a daemon restart, which is undesired behavior. (see #2286)
+ */
+ if (bgp->autoshutdown)
+ vty_out(vty, " bgp default shutdown\n");
+
/* No auto-summary */
if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
vty_out(vty, " no auto-summary\n");
}
}
-extern void bgp_snmp_init(void);
-
static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
{
struct vrf *vrf = NULL;
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
-/* BGP router distinguisher value. */
-#define BGP_RD_SIZE 8
-
-struct bgp_rd {
- uint8_t val[BGP_RD_SIZE];
-};
-
+/* Route map direction */
#define RMAP_IN 0
#define RMAP_OUT 1
#define RMAP_MAX 2
extern int peer_group_bind(struct bgp *, union sockunion *, struct peer *,
struct peer_group *, as_t *);
-extern int peer_group_unbind(struct bgp *, struct peer *, struct peer_group *);
extern int peer_flag_set(struct peer *, uint32_t);
extern int peer_flag_unset(struct peer *, uint32_t);
h = bgp->rfapi;
- assert(!CHECK_FLAG(h->flags, RFAPI_INCALLBACK));
+ assert(h != NULL && !CHECK_FLAG(h->flags, RFAPI_INCALLBACK));
if (CHECK_FLAG(rfd->flags,
RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)
memset(optary, 0, sizeof(optary));
optary[opt_next].v.l2addr.logical_net_id =
strtoul(argv[14]->arg, NULL, 10);
- if ((rc = rfapiStr2EthAddr(argv[12]->arg,
- &optary[opt_next].v.l2addr.macaddr))) {
+ if (rfapiStr2EthAddr(argv[12]->arg,
+ &optary[opt_next].v.l2addr.macaddr)) {
vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
nhp->vn_options = NULL;
XFREE(MTYPE_RFAPI_NEXTHOP, nhp);
- nhp = NULL;
}
}
static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
{
- struct rfapi_cfg *hc;
struct route_node *rn;
struct bgp_info *ri;
if (!bgp)
return;
- if (!(hc = bgp->rfapi_cfg))
+ if (!(bgp->rfapi_cfg))
return;
if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
struct bgp_info *info) /* unicast info */
{
afi_t afi = family2afi(prefix->family);
- struct rfapi_cfg *hc = NULL;
struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
return;
}
- if (!(hc = bgp->rfapi_cfg)) {
+ if (!(bgp->rfapi_cfg)) {
vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
__func__);
return;
struct peer *peer = info->peer;
struct attr *attr = info->attr;
struct attr hattr;
- struct rfapi_cfg *hc = NULL;
+ struct rfapi_cfg *hc = bgp->rfapi_cfg;
struct attr *iattr = NULL;
struct rfapi_ip_addr vnaddr;
return;
}
- if (!(hc = bgp->rfapi_cfg)) {
+ if (!hc) {
vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
__func__);
return;
struct peer *peer = info->peer;
struct attr *attr = info->attr;
struct attr hattr;
- struct rfapi_cfg *hc = NULL;
struct attr *iattr = NULL;
struct rfapi_ip_addr vnaddr;
return;
}
- if (!(hc = bgp->rfapi_cfg)) {
+ if (!(bgp->rfapi_cfg)) {
vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
__func__);
return;
struct rfapi_descriptor *rfd;
vncHDBgpDirect.peer = bi->peer;
+ assert(bi->extra);
+
rfd = bi->extra->vnc.export
.rfapi_handle;
])
dnl if the user has specified any CFLAGS, override our settings
-if test "x${enable_dev_build}" = "xyes"; then
+if test "x${enable_gcov}" = "xyes"; then
+ if test "z$orig_cflags" = "z"; then
+ AC_C_FLAG([-coverage])
+ AC_C_FLAG([-O0])
+ fi
+
+ LDFLAGS="${LDFLAGS} -lgcov"
+elif test "x${enable_dev_build}" = "xyes"; then
AC_DEFINE(DEV_BUILD,,Build for development)
if test "z$orig_cflags" = "z"; then
AC_C_FLAG([-g3])
AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
AC_ARG_ENABLE([numeric_version],
AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
+AC_ARG_ENABLE([gcov],
+ AS_HELP_STRING([--enable-gcov], [Add code coverage information]))
AS_IF([test "${enable_clippy_only}" != "yes"], [
AC_CHECK_HEADERS(json-c/json.h)
AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
+dnl --------------------
+dnl Enable code coverage
+dnl --------------------
+AM_CONDITIONAL([HAVE_GCOV],[test '!' "$enable_gcov" = no])
+
dnl ------------------------------------
dnl Alpine only accepts numeric versions
dnl ------------------------------------
developer/ldpd-basic-test-setup.md \
developer/library.rst \
developer/Makefile.in \
+ developer/maintainer-release-build.rst \
developer/memtypes.rst \
developer/modules.rst \
developer/next-hop-tracking.rst \
--- /dev/null
+Release Build Procedure for FRR maintainers
+=========================================================
+
+1. Rename branch (if needed)
+
+.. code-block:: shell
+
+ git clone git@github.com:FRRouting/frr.git
+ cd frr
+ git checkout dev/5.0
+ git push origin :refs/heads/dev/5.0
+ git push origin dev/5.0:refs/heads/stable/5.0
+
+2. Checkout the new stable branch:
+
+.. code-block:: shell
+
+ git checkout stable/5.0
+
+3. Update Changelog for RedHat Package:
+
+ Edit :file:`redhat/frr.spec.in` and look for the ``%changelog`` section:
+
+ - Change last (top of list) entry from ``%{version}`` to previous fixed
+ version number, i.e.::
+
+ * Tue Nov 7 2017 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+
+ to::
+
+ * Tue Nov 7 2017 Martin Winter <mwinter@opensourcerouting.org> - 3.0.2
+
+ - Add new entry to the top of the list with ``%{version}`` tag and changelog
+ for version.
+ Make sure to watch the format, i.e. the day is always 2 characters, with
+ the 1st character being a space if the day is one digit.
+
+4. Update Changelog for Debian Packages:
+
+ Edit :file:`debianpkg/changelog.in`:
+
+ - Change last (top of list) entry from ``@VERSION@`` to previous fixed
+ version number, i.e.::
+
+ frr (@VERSION@) RELEASED; urgency=medium
+
+ to::
+
+ frr (3.0.2) RELEASED; urgency=medium
+
+ - Add a new entry to the top of the list with a ``@VERSION@`` tag and
+ changelog for version.
+
+5. Change main version number:
+
+ - Edit :file:`configure.ac` and change version in the ``AC_INIT`` command
+ - Create a new entry with the version as ``%{version}`` tag
+
+6. Test building at least a Red Hat and Ubuntu package (or create a PR to have
+ the CI system test them)
+
+7. Commit the changes, adding the changelog to the commit message
+
+8. Create a git tag for the version:
+
+ .. code-block:: shell
+
+ git tag -a frr-5.0 -m "FRRouting Release 5.0"
+
+9. Push the commit and tag(s) and watch for errors on CI:
+
+ .. code-block:: shell
+
+ git push
+ git push --tags
+
+10. Kick off the Release build plan on the CI system for the correct release
+
+11. Send a Release Announcement with changes to
+ ``announce@lists.frrouting.org``
+
+12. Kick off the Snapcraft build plan for the correct release
+
+13. After CI plans succeed, release on GitHub by going to
+ https://github.com/FRRouting/frr/releases and selecting "Draft a new
+ release".
+
+14. Deploy Snapcraft release (after CI system finishes the tests for snapcraft
+ testplan)
utilized but pure ReST is preferred where possible. See
:ref:`documentation`.
+Code Reviews
+============
+
+Code quality is paramount for any large program. Consequently we require
+reviews of all submitted patches by at least one person other than the
+submitter before the patch is merged.
+
+Because of the nature of the software, FRR's maintainer list (i.e. those with
+commit permissions) tends to contain employees / members of various
+organizations. In order to prevent conflicts of interest, we use an honor
+system in which submissions from an individual representing one company should
+be merged by someone unaffiliated with that company.
+
+Guidelines for code review
+""""""""""""""""""""""""""
+
+- As a rule of thumb, the depth of the review should be proportional to the
+ scope and / or impact of the patch.
+
+- Anyone may review a patch.
+
+- When using GitHub reviews, marking "Approve" on a code review indicates
+ willingness to merge the PR.
+
+- For individuals with merge rights, marking "Changes requested" is equivalent
+ to a NAK.
+
+- For a PR you marked with "Changes requested", please respond to updates in a
+ timely manner to avoid impeding the flow of development.
+
+
Coding Practices & Style
========================
neighbor 10.0.0.3 remote-as 4
neighbor 10.0.0.4 remote-as 5
-.. index:: show ip bgp view NAME
-.. clicmd:: show ip bgp view NAME
+.. index:: show [ip] bgp view NAME
+.. clicmd:: show [ip] bgp view NAME
Display the routing table of BGP view ``NAME``.
Show all enabled debugs.
-.. index:: [no] debug neighbor-events
-.. clicmd:: [no] debug neighbor-events
+.. index:: [no] debug bgp neighbor-events
+.. clicmd:: [no] debug bgp neighbor-events
Enable or disable debugging for neighbor events. This provides general
information on BGP events such as peer connection / disconnection, session
establishment / teardown, and capability negotiation.
-.. index:: [no] debug updates
-.. clicmd:: [no] debug updates
+.. index:: [no] debug bgp updates
+.. clicmd:: [no] debug bgp updates
Enable or disable debugging for BGP updates. This provides information on
BGP UPDATE messages transmitted and received between local and remote
instances.
-.. index:: [no] debug keepalives
-.. clicmd:: [no] debug keepalives
+.. index:: [no] debug bgp keepalives
+.. clicmd:: [no] debug bgp keepalives
Enable or disable debugging for BGP keepalives. This provides information on
BGP KEEPALIVE messages transmitted and received between local and remote
Displaying BGP Information
==========================
+The following four commands display the IPv6 and IPv4 routing tables, depending
+on whether or not the ``ip`` keyword is used.
+Actually, :clicmd:`show ip bgp` command was used on older `Quagga` routing
+daemon project, while :clicmd:`show bgp` command is the new format. The choice
+has been done to keep old format with IPv4 routing table, while new format
+displays IPv6 routing table.
+
.. index:: show ip bgp
.. clicmd:: show ip bgp
.. index:: show ip bgp A.B.C.D
.. clicmd:: show ip bgp A.B.C.D
-.. index:: show ip bgp X:X::X:X
-.. clicmd:: show ip bgp X:X::X:X
+.. index:: show bgp
+.. clicmd:: show bgp
+
+.. index:: show bgp X:X::X:X
+.. clicmd:: show bgp X:X::X:X
These commands display BGP routes. When no route is specified, the default
- is to display all IPv4 BGP routes.
+ is to display all BGP routes.
::
Total number of prefixes 1
-.. index:: show ip bgp regexp LINE
-.. clicmd:: show ip bgp regexp LINE
+Some other commands provide additional options for filtering the output.
+
+.. index:: show [ip] bgp regexp LINE
+.. clicmd:: show [ip] bgp regexp LINE
This command displays BGP routes using AS path regular expression
(:ref:`bgp-regular-expressions`).
-.. index:: show bgp <ipv4|ipv6> summary
-.. clicmd:: show bgp <ipv4|ipv6> summary
+.. index:: show [ip] bgp summary
+.. clicmd:: show [ip] bgp summary
Show a bgp peer summary for the specified address family.
-.. index:: show bgp <ipv4|ipv6> neighbor [PEER]
-.. clicmd:: show bgp <ipv4|ipv6> neighbor [PEER]
+The old command structure :clicmd:`show ip bgp` may be removed in the future
+and should no longer be used. In order to reach the other BGP routing tables
+other than the IPv6 routing table given by :clicmd:`show bgp`, the new command
+structure is extended with :clicmd:`show bgp [afi] [safi]`.
+
+.. index:: show bgp [afi] [safi]
+.. clicmd:: show bgp [afi] [safi]
+
+.. index:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
+.. clicmd:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
- This command shows information on a specific BGP `peer`.
+ These commands display BGP routes for the specific routing table indicated by
+ the selected afi and the selected safi. If no afi and no safi value is given,
+ the command falls back to the default IPv6 routing table
-.. index:: show bgp <ipv4|ipv6> dampening dampened-paths
-.. clicmd:: show bgp <ipv4|ipv6> dampening dampened-paths
+.. index:: show bgp [afi] [safi] summary
+.. clicmd:: show bgp [afi] [safi] summary
- Display paths suppressed due to dampening.
+ Show a bgp peer summary for the specified address family, and subsequent
+ address-family.
-.. index:: show bgp <ipv4|ipv6> dampening flap-statistics
-.. clicmd:: show bgp <ipv4|ipv6> dampening flap-statistics
+.. index:: show bgp [afi] [safi] neighbor [PEER]
+.. clicmd:: show bgp [afi] [safi] neighbor [PEER]
- Display flap statistics of routes.
+ This command shows information on a specific BGP peer of the relevant
+ afi and safi selected.
+
+.. index:: show bgp [afi] [safi] dampening dampened-paths
+.. clicmd:: show bgp [afi] [safi] dampening dampened-paths
+
+ Display paths suppressed due to dampening of the selected afi and safi
+ selected.
+
+.. index:: show bgp [afi] [safi] dampening flap-statistics
+.. clicmd:: show bgp [afi] [safi] dampening flap-statistics
+
+ Display flap statistics of routes of the selected afi and safi selected.
.. _bgp-display-routes-by-community:
This commands displays BGP routes that matches a regular
expression `line` (:ref:`bgp-regular-expressions`).
-.. index:: show ip bgp ipv4 vpn
-.. clicmd:: show ip bgp ipv4 vpn
+.. index:: show [ip] bgp ipv4 vpn
+.. clicmd:: show [ip] bgp ipv4 vpn
-.. index:: show ipv6 bgp ipv6 vpn
-.. clicmd:: show ipv6 bgp ipv6 vpn
+.. index:: show [ip] bgp ipv6 vpn
+.. clicmd:: show [ip] bgp ipv6 vpn
Print active IPV4 or IPV6 routes advertised via the VPN SAFI.
.. include:: rpki.rst
+.. include:: flowspec.rst
+
.. [#med-transitivity-rant] For some set of objects to have an order, there *must* be some binary ordering relation that is defined for *every* combination of those objects, and that relation *must* be transitive. I.e.:, if the relation operator is <, and if a < b and b < c then that relation must carry over and it *must* be that a < c for the objects to have an order. The ordering relation may allow for equality, i.e. a < b and b < a may both be true and imply that a and b are equal in the order and not distinguished by it, in which case the set has a partial order. Otherwise, if there is an order, all the objects have a distinct place in the order and the set has a total order)
.. [bgp-route-osci-cond] McPherson, D. and Gill, V. and Walton, D., "Border Gateway Protocol (BGP) Persistent Route Oscillation Condition", IETF RFC3345
.. [stable-flexible-ibgp] Flavel, A. and M. Roughan, "Stable and flexible iBGP", ACM SIGCOMM 2009
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'rpki.rst', 'routeserver.rst', 'ospf_fundamentals.rst']
+exclude_patterns = ['_build', 'rpki.rst', 'routeserver.rst',
+ 'ospf_fundamentals.rst', 'flowspec.rst']
# The reST default role (used for this markup: `text`) to use for all
# documents.
--- /dev/null
+.. _flowspec:
+
+Flowspec
+========
+
+.. _features-of-the-current-implementation-flowspec:
+
+Overview
+---------
+
+Flowspec introduces a new :abbr:`NLRI (Network Layer Reachability Information)`
+encoding format that is used to distribute traffic rule flow specifications.
+Basically, instead of simply relying on destination IP address for IP prefixes,
+the IP prefix is replaced by a n-tuple consisting of a rule. That rule can be a
+more or less complex combination of the following:
+
+
+- Network source/destination (can be one or the other, or both).
+- Layer 4 information for UDP/TCP: source port, destination port, or any port.
+- Layer 4 information for ICMP type and ICMP code.
+- Layer 4 information for TCP Flags.
+- Layer 3 information: DSCP value, Protocol type, packet length, fragmentation.
+- Misc layer 4 TCP flags.
+
+A combination of the above rules is applied for traffic filtering. This is
+encoded as part of specific BGP extended communities and the action can range
+from the obvious rerouting (to nexthop or to separate VRF) to shaping, or
+discard.
+
+The following IETF drafts and RFCs have been used to implement FRR Flowspec:
+
+- :rfc:`5575`
+- [Draft-IETF-IDR-Flowspec-redirect-IP]_
+
+.. _design-principles-flowspec:
+
+Design Principles
+-----------------
+
+FRR implements the Flowspec client side, that is to say that BGP is able to
+receive Flowspec entries, but is not able to act as manager and send Flowspec
+entries.
+
+Linux provides the following mechanisms to implement policy based routing:
+
+- Filtering the traffic with ``Netfilter``.
+ ``Netfilter`` provides a set of tools like ``ipset`` and ``iptables`` that are
+ powerful enough to be able to filter such Flowspec filter rule.
+
+- using non standard routing tables via ``iproute2`` (via the ``ip rule``
+ command provided by ``iproute2``).
+ ``iproute2`` is already used by FRR's :ref:`pbr` daemon which provides basic
+ policy based routing based on IP source and destination criterion.
+
+Below example is an illustration of what Flowspec will inject in the underlying
+system:
+
+.. code-block:: shell
+
+ # linux shell
+ ipset create match0x102 hash:net,net counters
+ ipset add match0x102 32.0.0.0/16,40.0.0.0/16
+ iptables -N match0x102 -t mangle
+ iptables -A match0x102 -t mangle -j MARK --set-mark 102
+ iptables -A match0x102 -t mangle -j ACCEPT
+ iptables -i ntfp3 -t mangle -I PREROUTING -m set --match-set match0x102
+ src,dst -g match0x102
+ ip rule add fwmark 102 lookup 102
+ ip route add 40.0.0.0/16 via 44.0.0.2 table 102
+
+For handling an incoming Flowspec entry, the following workflow is applied:
+
+- Incoming Flowspec entries are handled by *bgpd*, stored in the BGP RIB.
+- Flowspec entry is installed according to its complexity.
+
+It will be installed if one of the following filtering action is seen on the
+BGP extended community: either redirect IP, or redirect VRF, in conjunction
+with rate option, for redirecting traffic. Or rate option set to 0, for
+discarding traffic.
+
+According to the degree of complexity of the Flowspec entry, it will be
+installed in *zebra* RIB. For more information about what is supported in the
+FRR implementation as rule, see :ref:`flowspec-known-issues` chapter. Flowspec
+entry is split in several parts before being sent to *zebra*.
+
+- *zebra* daemon receives the policy routing configuration
+
+Policy Based Routing entities necessary to policy route the traffic in the
+underlying system, are received by *zebra*. Two filtering contexts will be
+created or appended in ``Netfilter``: ``ipset`` and ``iptable`` context. The
+former is used to define an IP filter based on multiple criterium. For
+instance, an ipset ``net:net`` is based on two ip addresses, while
+``net,port,net`` is based on two ip addresses and one port (for ICMP, UDP, or
+TCP). The way the filtering is used (for example, is src port or dst port
+used?) is defined by the latter filtering context. ``iptable`` command will
+reference the ``ipset`` context and will tell how to filter and what to do. In
+our case, a marker will be set to indicate ``iproute2`` where to forward the
+traffic to. Sometimes, for dropping action, there is no need to add a marker;
+the ``iptable`` will tell to drop all packets matching the ``ipset`` entry.
+
+Configuration Guide
+-------------------
+
+In order to configure an IPv4 Flowspec engine, use the following configuration.
+As of today, it is only possible to configure Flowspec on the default VRF.
+
+.. code-block:: frr
+
+ router bgp <AS>
+ neighbor <A.B.C.D> remote-as <remoteAS>
+ address-family ipv4 flowspec
+ neighbor <A.B.C.D> activate
+ exit
+ exit
+
+You can see Flowspec entries, by using one of the following show commands:
+
+.. index:: show bgp ipv4 flowspec [detail | A.B.C.D]
+.. clicmd:: show bgp ipv4 flowspec [detail | A.B.C.D]
+
+
+Per-interface configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+One nice feature to use is the ability to apply Flowspec to a specific
+interface, instead of applying it to the whole machine. Despite the following
+IETF draft [Draft-IETF-IDR-Flowspec-Interface-Set]_ is not implemented, it is
+possible to manually limit Flowspec application to some incoming interfaces.
+Actually, not using it can result to some unexpected behaviour like accounting
+twice the traffic, or slow down the traffic (filtering costs). To limit
+Flowspec to one specific interface, use the following command, under
+`flowspec address-family` node.
+
+.. index:: [no] local-install <IFNAME | any>
+.. clicmd:: [no] local-install <IFNAME | any>
+
+By default, Flowspec is activated on all interfaces. Installing it to a named
+interface will result in allowing only this interface. Conversely, enabling any
+interface will flush all previously configured interfaces.
+
+VRF redirection
+^^^^^^^^^^^^^^^
+
+Another nice feature to configure is the ability to redirect traffic to a
+separate VRF. This feature does not go against the ability to configure
+Flowspec only on default VRF. Actually, when you receive incoming BGP flowspec
+entries on that default VRF, you can redirect traffic to an other VRF.
+
+As a reminder, BGP flowspec entries have a BGP extended community that contains
+a Route Target. Finding out a local VRF based on Route Target consists in the
+following:
+
+- A configuration of each VRF must be done, with its Route Target set
+ Each VRF is being configured within a BGP VRF instance with its own Route
+ Target list. Route Target accepted format matches the following:
+ ``A.B.C.D:U16``, or ``U16:U32``, ``U32:U16``.
+
+- The first VRF with the matching Route Target will be selected to route traffic
+ to. Use the following command under ipv4 unicast address-family node
+
+.. index:: [no] rt redirect import RTLIST...
+.. clicmd:: [no] rt redirect import RTLIST...
+
+In order to illustrate, if the Route Target configured in the Flowspec entry is
+``E.F.G.H:II``, then a BGP VRF instance with the same Route Target will be set
+set. That VRF will then be selected. The below full configuration example
+depicts how Route Targets are configured and how VRFs and cross VRF
+configuration is done. Note that the VRF are mapped on Linux Network
+Namespaces. For data traffic to cross VRF boundaries, virtual ethernet
+interfaces are created with private IP adressing scheme.
+
+.. code-block:: frr
+
+ router bgp <ASx>
+ neighbor <A.B.C.D> remote-as <ASz>
+ address-family ipv4 flowspec
+ neighbor A.B.C.D activate
+ exit
+ exit
+ router bgp <ASy> vrf vrf2
+ address-family ipv4 unicast
+ rt redirect import <E.F.G.H:II>
+ exit
+ exit
+
+Flowspec monitoring & troubleshooting
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can monitor policy-routing objects by using one of the following commands.
+Those command rely on the filtering contexts configured from BGP, and get the
+statistics information retrieved from the underlying system. In other words,
+those statistics are retrieved from ``Netfilter``.
+
+.. index:: show pbr ipset IPSETNAME | iptable
+.. clicmd:: show pbr ipset IPSETNAME | iptable
+
+``IPSETNAME`` is the policy routing object name created by ``ipset``. About
+rule contexts, it is possible to know which rule has been configured to
+policy-route some specific traffic. The :clicmd:`show pbr iptable` command
+displays for forwarded traffic, which table is used. Then it is easy to use
+that table identifier to dump the routing table that the forwarded traffic will
+match.
+
+.. code-block:: frr
+
+.. index:: show ip route table TABLEID
+.. clicmd:: show ip route table TABLEID
+
+ ``TABLEID`` is the table number identifier referencing the non standard
+ routing table used in this example.
+
+.. index:: [no] debug bgp flowspec
+.. clicmd:: [no] debug bgp flowspec
+
+ You can troubleshoot Flowspec, or BGP policy based routing. For instance, if
+ you encounter some issues when decoding a Flowspec entry, you should enable
+ :clicmd:`debug bgp flowspec`.
+
+.. index:: [no] debug bgp pbr [error]
+.. clicmd:: [no] debug bgp pbr [error]
+
+ If you fail to apply the flowspec entry into *zebra*, there should be some
+ relationship with policy routing mechanism. Here,
+ :clicmd:`debug bgp pbr error` could help.
+
+ To get information about policy routing contexts created/removed, only use
+ :clicmd:`debug bgp pbr` command.
+
+Ensuring that a Flowspec entry has been correctly installed and that incoming
+traffic is policy-routed correctly can be checked as demonstrated below. First
+of all, you must check whether the Flowspec entry has been installed or not.
+
+.. code-block:: frr
+
+ CLI# show bgp ipv4 flowspec 5.5.5.2/32
+ BGP flowspec entry: (flags 0x418)
+ Destination Address 5.5.5.2/32
+ IP Protocol = 17
+ Destination Port >= 50 , <= 90
+ FS:redirect VRF RT:255.255.255.255:255
+ received for 18:41:37
+ installed in PBR (match0x271ce00)
+
+This means that the Flowspec entry has been installed in an ``iptable`` named
+``match0x271ce00``. Once you have confirmation it is installed, you can check
+whether you find the associate entry by executing following command. You can
+also check whether incoming traffic has been matched by looking at counter
+line.
+
+.. code-block:: frr
+
+ CLI# show pbr ipset match0x271ce00
+ IPset match0x271ce00 type net,port
+ to 5.5.5.0/24:proto 6:80-120 (8)
+ pkts 1000, bytes 1000000
+ to 5.5.5.2:proto 17:50-90 (5)
+ pkts 1692918, bytes 157441374
+
+As you can see, the entry is present. note that an ``iptable`` entry can be
+used to host several Flowspec entries. In order to know where the matching
+traffic is redirected to, you have to look at the policy routing rules. The
+policy-routing is done by forwarding traffic to a routing table number. That
+routing table number is reached by using a ``iptable``. The relationship
+between the routing table number and the incoming traffic is a ``MARKER`` that
+is set by the IPtable referencing the IPSet. In Flowspec case, ``iptable``
+referencing the ``ipset`` context have the same name. So it is easy to know
+which routing table is used by issuing following command:
+
+.. code-block:: frr
+
+ CLI# show pbr iptable
+ IPtable match0x271ce00 action redirect (5)
+ pkts 1700000, bytes 158000000
+ table 257, fwmark 257
+ ...
+
+As you can see, by using following Linux commands, the MARKER ``0x101`` is
+present in both ``iptable`` and ``ip rule`` contexts.
+
+.. code-block:: shell
+
+ # iptables -t mangle --list match0x271ce00 -v
+ Chain match0x271ce00 (1 references)
+ pkts bytes target prot opt in out source destination
+ 1700K 158M MARK all -- any any anywhere anywhere
+ MARK set 0x101
+ 1700K 158M ACCEPT all -- any any anywhere anywhere
+
+ # ip rule list
+ 0:from all lookup local
+ 0:from all fwmark 0x101 lookup 257
+ 32766:from all lookup main
+ 32767:from all lookup default
+
+This allows us to see where the traffic is forwarded to.
+
+.. _flowspec-known-issues:
+
+Limitations / Known Issues
+--------------------------
+
+As you can see, Flowspec is rich and can be very complex. As of today, not all
+Flowspec rules will be able to be converted into Policy Based Routing actions.
+
+- The ``Netfilter`` driver is not integrated into FRR yet. Not having this
+ piece of code prevents from injecting flowspec entries into the underlying
+ system.
+
+- There are some limitations around filtering contexts
+
+ If I take example of UDP ports, or TCP ports in Flowspec, the information
+ can be a range of ports, or a unique value. This case is handled.
+ However, complexity can be increased, if the flow is a combination of a list
+ of range of ports and an enumerate of unique values. Here this case is not
+ handled. Similarly, it is not possible to create a filter for both src port
+ and dst port. For instance, filter on src port from [1-1000] and dst port =
+ 80. The same kind of complexity is not possible for packet length, ICMP type,
+ ICMP code.
+
+There are some other known issues:
+
+- The validation procedure depicted in :rfc:`5575` is not available.
+
+ This validation procedure has not been implemented, as this feature was not
+ used in the existing setups you shared wih us.
+
+- The filtering action shaper value, if positive, is not used to apply shaping.
+
+ If value is positive, the traffic is redirected to the wished destination,
+ without any other action configured by Flowspec.
+ It is recommended to configure Quality of Service if needed, more globally on
+ a per interface basis.
+
+- Upon an unexpected crash or other event, *zebra* may not have time to flush
+ PBR contexts.
+
+ That is to say ``ipset``, ``iptable`` and ``ip rule`` contexts. This is also a
+ consequence due to the fact that ip rule / ipset / iptables are not discovered
+ at startup (not able to read appropriate contexts coming from Flowspec).
+
+Appendix
+--------
+
+More information with a public presentation that explains the design of Flowspec
+inside FRRouting.
+
+[Presentation]_
+
+.. [Draft-IETF-IDR-Flowspec-redirect-IP] <https://tools.ietf.org/id/draft-ietf-idr-flowspec-redirect-ip-02.txt>
+.. [Draft-IETF-IDR-Flowspec-Interface-Set] <https://tools.ietf.org/id/draft-ietf-idr-flowspec-interfaceset-03.txt>
+.. [Presentation] <https://docs.google.com/presentation/d/1ekQygUAG5yvQ3wWUyrw4Wcag0LgmbW1kV02IWcU4iUg/edit#slide=id.g378f0e1b5e_1_44>
hardcoded arrays that FRR builds towards, so we need to know how big to
make these arrays at build time.
+.. option:: --enable-gcov
+
+ Code coverage reports from gcov require adjustments to the C and LD flags.
+ With this option, gcov instrumentation is added to the build and coverage
+ reports are created during execution. The check-coverage make target is
+ also created to ease report uploading to codecov.io. The upload requires
+ the COMMIT (git hash) and TOKEN (codecov upload token) environment variables
+ be set.
+
You may specify any combination of the above options to the configure
script. By default, the executables are placed in :file:`/usr/local/sbin`
and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/`
- Route maps can be configured to match a specific RPKI validation state. This
allows the creation of local policies, which handle BGP routes based on the
outcome of the Prefix Origin Validation.
+- Updates from the RPKI cache servers are directly applied and path selection
+ is updated accordingly. (Soft reconfiguration **must** be enabled for this
+ to work).
.. _enabling-rpki:
.. _configuring-rpki-rtr-cache-servers:
+.. index:: daemons.conf
+
+ When first installing FRR with RPKI support from the pre-packaged binaries. Remember
+ to append '-M rpki' in the /etc/frr/daemons.conf file to the bgpd_options.
+
+ bgpd_options=" --daemon -A 127.0.0.1 -M rpki"
+ instead of the default setting
+ bgpd_options=" --daemon -A 127.0.0.1"
+
+
+ Else you will encounter an error when trying to enter RPKI configuration mode. Because
+ the rpki module is not loaded when the BGP daemon is initialized.
+
+ Examples of the error:
+
+ router(config)# debug rpki
+ % [BGP] Unknown command: debug rpki
+
+ router(config)# rpki
+ % [BGP] Unknown command: rpki
+
+ Note that the rpki commands will be available in vtysh when running 'find rpki'.
+ Even if the RPKI module is NOT loaded.
+ The RPKI commands will be unavailable if you try running the same command in the
+ cli specific to the BGP daemon.
+
Configuring RPKI/RTR Cache Servers
----------------------------------
show ip table vrf r1-cust1 table 43
+.. _zebra-mpls:
+
+MPLS Commands
+=============
+
+You can configure static mpls entries in zebra. Basically, handling MPLS
+consists of popping, swapping or pushing labels to IP packets.
+
+MPLS Acronyms
+-------------
+
+:abbr:`LSR (Labeled Switch Router)`
+ Networking devices handling labels used to forward traffic between and through
+ them.
+
+:abbr:`LER (Labeled Edge Router)`
+ A Labeled edge router is located at the edge of an MPLS network, generally
+ between an IP network and an MPLS network.
+
+MPLS Push Action
+----------------
+
+The push action is generally used for LER devices, which want to encapsulate
+all traffic for a wished destination into an MPLS label. This action is stored
+in routing entry, and can be configured like a route:
+
+.. index:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
+.. clicmd:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
+
+ NETWORK ans MASK stand for the IP prefix entry to be added as static
+ route entry.
+ GATEWAY is the gateway IP address to reach, in order to reach the prefix.
+ INTERFACE is the interface behind which the prefix is located.
+ LABEL is the MPLS label to use to reach the prefix abovementioned.
+
+ You can check that the static entry is stored in the zebra RIB database, by
+ looking at the presence of the entry.
+
+ ::
+
+ zebra(configure)# ip route 1.1.1.1/32 10.0.1.1 label 777
+ zebra# show ip route
+ Codes: K - kernel route, C - connected, S - static, R - RIP,
+ O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
+ T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
+ F - PBR,
+ > - selected route, * - FIB route
+
+ S>* 1.1.1.1/32 [1/0] via 10.0.1.1, r2-eth0, label 777, 00:39:42
+
+MPLS Swap and Pop Action
+------------------------
+
+The swap action is generally used for LSR devices, which swap a packet with a
+label, with an other label. The Pop action is used on LER devices, at the
+termination of the MPLS traffic; this is used to remove MPLS header.
+
+.. index:: [no] mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null
+.. clicmd:: [no] mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null
+
+ INCOMING_LABEL and OUTGOING_LABEL are MPLS labels with values ranging from 16
+ to 1048575.
+ GATEWAY is the gateway IP address where to send MPLS packet.
+ The outgoing label can either be a value or have an explicit-null label header. This
+ specific header can be read by IP devices. The incoming label can also be removed; in
+ that case the implicit-null keyword is used, and the outgoing packet emitted is an IP
+ packet without MPLS header.
+
+You can check that the MPLS actions are stored in the zebra MPLS table, by looking at the
+presence of the entry.
+
+.. index:: show mpls table
+.. clicmd:: show mpls table
+
+::
+
+ zebra(configure)# mpls lsp 18 10.125.0.2 implicit-null
+ zebra(configure)# mpls lsp 19 10.125.0.2 20
+ zebra(configure)# mpls lsp 21 10.125.0.2 explicit-null
+ zebra# show mpls table
+ Inbound Outbound
+ Label Type Nexthop Label
+ -------- ------- --------------- --------
+ 18 Static 10.125.0.2 implicit-null
+ 19 Static 10.125.0.2 20
+ 21 Static 10.125.0.2 IPv4 Explicit Null
+
+
.. _multicast-rib-commands:
Multicast RIB Commands
--- /dev/null
+FROM alpine:3.7
+ARG commit
+ARG token
+ENV COMMIT=${commit}
+ENV TOKEN=${token}
+ADD . /src
+RUN cd /src && \
+ source alpine/APKBUILD.in && \
+ apk add --no-cache alpine-sdk $makedepends $checkdepends && \
+ ./bootstrap.sh && \
+ ./configure --enable-gcov
+ENTRYPOINT [ "/bin/sh", "-c", "cd /src && make && make -j 1 check-coverage" ]
if (dash)
dash[0] = '\0';
- ret = sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR);
+ ret = sscanf(ver_string, "%" SCNu32 ".%" SCNu32, &FRR_MAJOR,
+ &FRR_MINOR);
if (ret != 2)
zlog_err("Did not Properly parse %s, please fix VERSION string",
VERSION);
zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
return NULL;
}
- if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
+ if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */
{
zlog_warn(
"eigrp_recv_packet: discarding runt packet of length %d "
"(ip header size is %u)",
- ret, (unsigned int)sizeof(iph));
+ ret, (unsigned int)sizeof(*iph));
return NULL;
}
void recoverscope(struct sockaddr_in6 *);
void addscope(struct sockaddr_in6 *, uint32_t);
void clearscope(struct in6_addr *);
-struct sockaddr *addr2sa(int af, union ldpd_addr *, uint16_t);
+void addr2sa(int af, const union ldpd_addr *, uint16_t,
+ union sockunion *su);
void sa2addr(struct sockaddr *, int *, union ldpd_addr *,
in_port_t *);
socklen_t sockaddr_len(struct sockaddr *);
int
nbr_establish_connection(struct nbr *nbr)
{
- struct sockaddr_storage local_sa;
- struct sockaddr_storage remote_sa;
+ union sockunion local_su;
+ union sockunion remote_su;
struct adj *adj;
struct nbr_params *nbrp;
#ifdef __OpenBSD__
#endif
}
- memcpy(&local_sa, addr2sa(nbr->af, &nbr->laddr, 0), sizeof(local_sa));
- memcpy(&remote_sa, addr2sa(nbr->af, &nbr->raddr, LDP_PORT),
- sizeof(local_sa));
+ addr2sa(nbr->af, &nbr->laddr, 0, &local_su);
+ addr2sa(nbr->af, &nbr->raddr, LDP_PORT, &remote_su);
if (nbr->af == AF_INET6 && nbr->raddr_scope)
- addscope((struct sockaddr_in6 *)&remote_sa, nbr->raddr_scope);
+ addscope(&remote_su.sin6, nbr->raddr_scope);
- if (bind(nbr->fd, (struct sockaddr *)&local_sa,
- sockaddr_len((struct sockaddr *)&local_sa)) == -1) {
+ if (bind(nbr->fd, &local_su.sa, sockaddr_len(&local_su.sa)) == -1) {
log_warn("%s: error while binding socket to %s", __func__,
- log_sockaddr((struct sockaddr *)&local_sa));
+ log_sockaddr(&local_su.sa));
close(nbr->fd);
return (-1);
}
send_hello(adj->source.type, adj->source.link.ia,
adj->source.target);
- if (connect(nbr->fd, (struct sockaddr *)&remote_sa,
- sockaddr_len((struct sockaddr *)&remote_sa)) == -1) {
+ if (connect(nbr->fd, &remote_su.sa, sockaddr_len(&remote_su.sa))
+ == -1) {
if (errno == EINPROGRESS) {
thread_add_write(master, nbr_connect_cb, nbr, nbr->fd,
&nbr->ev_connect);
return (0);
}
log_warn("%s: error while connecting to %s", __func__,
- log_sockaddr((struct sockaddr *)&remote_sa));
+ log_sockaddr(&remote_su.sa));
close(nbr->fd);
return (-1);
}
send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia,
void *pkt, size_t len)
{
- struct sockaddr *sa;
+ union sockunion su;
switch (af) {
case AF_INET:
fatalx("send_packet: unknown af");
}
- sa = addr2sa(af, dst, LDP_PORT);
- if (sendto(fd, pkt, len, 0, sa, sockaddr_len(sa)) == -1) {
+ addr2sa(af, dst, LDP_PORT, &su);
+ if (sendto(fd, pkt, len, 0, &su.sa, sockaddr_len(&su.sa)) == -1) {
log_warn("%s: error sending packet to %s", __func__,
- log_sockaddr(sa));
+ log_sockaddr(&su.sa));
return (-1);
}
ssize_t n;
int len = 0;
int iov_cnt;
- struct sockaddr_storage ssrc, sdst, smask, dmask;
- struct sockaddr *saptr;
+ struct sockaddr_storage smask, dmask;
+ union sockunion su_src, su_dst;
if (!pid)
pid = getpid();
/* we need clean sockaddr... no ports set */
- memset(&ssrc, 0, sizeof(ssrc));
memset(&smask, 0, sizeof(smask));
- if ((saptr = addr2sa(af, src, 0)))
- memcpy(&ssrc, saptr, sizeof(ssrc));
+
+ addr2sa(af, src, 0, &su_src);
+
switch (af) {
case AF_INET:
memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
default:
return (-1);
}
- smask.ss_family = ssrc.ss_family;
- smask.ss_len = ssrc.ss_len;
+ smask.ss_family = su_src.sa.sa_family;
+ smask.ss_len = sockaddr_len(&su_src.sa);
- memset(&sdst, 0, sizeof(sdst));
memset(&dmask, 0, sizeof(dmask));
- if ((saptr = addr2sa(af, dst, 0)))
- memcpy(&sdst, saptr, sizeof(sdst));
+
+ addr2sa(af, dst, 0, &su_dst);
+
switch (af) {
case AF_INET:
memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
default:
return (-1);
}
- dmask.ss_family = sdst.ss_family;
- dmask.ss_len = sdst.ss_len;
+ dmask.ss_family = su_dst.sa.sa_family;
+ dmask.ss_len = sockaddr_len(&su_dst.sa);
memset(&smsg, 0, sizeof(smsg));
smsg.sadb_msg_version = PF_KEY_V2;
memset(&sa_src, 0, sizeof(sa_src));
sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
- sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
+ sa_src.sadb_address_len =
+ (sizeof(sa_src) + ROUNDUP(sockaddr_len(&su_src.sa))) / 8;
memset(&sa_dst, 0, sizeof(sa_dst));
sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
- sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
+ sa_dst.sadb_address_len =
+ (sizeof(sa_dst) + ROUNDUP(sockaddr_len(&su_dst.sa))) / 8;
sa.sadb_sa_auth = aalg;
sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
iov[iov_cnt].iov_base = &sa_dst;
iov[iov_cnt].iov_len = sizeof(sa_dst);
iov_cnt++;
- iov[iov_cnt].iov_base = &sdst;
- iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
+ iov[iov_cnt].iov_base = &su_dst;
+ iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_dst.sa));
smsg.sadb_msg_len += sa_dst.sadb_address_len;
iov_cnt++;
iov[iov_cnt].iov_base = &sa_src;
iov[iov_cnt].iov_len = sizeof(sa_src);
iov_cnt++;
- iov[iov_cnt].iov_base = &ssrc;
- iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
+ iov[iov_cnt].iov_base = &su_src;
+ iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_src.sa));
smsg.sadb_msg_len += sa_src.sadb_address_len;
iov_cnt++;
{
int fd, domain, proto;
union ldpd_addr addr;
- struct sockaddr_storage local_sa;
+ union sockunion local_su;
#ifdef __OpenBSD__
int opt;
#endif
case LDP_SOCKET_DISC:
/* listen on all addresses */
memset(&addr, 0, sizeof(addr));
- memcpy(&local_sa, addr2sa(af, &addr, LDP_PORT),
- sizeof(local_sa));
+ addr2sa(af, &addr, LDP_PORT, &local_su);
break;
case LDP_SOCKET_EDISC:
case LDP_SOCKET_SESSION:
addr = (ldp_af_conf_get(ldpd_conf, af))->trans_addr;
- memcpy(&local_sa, addr2sa(af, &addr, LDP_PORT),
- sizeof(local_sa));
+ addr2sa(af, &addr, LDP_PORT, &local_su);
/* ignore any possible error */
sock_set_bindany(fd, 1);
break;
close(fd);
return (-1);
}
- if (bind(fd, (struct sockaddr *)&local_sa,
- sockaddr_len((struct sockaddr *)&local_sa)) == -1) {
+ if (bind(fd, &local_su.sa, sockaddr_len(&local_su.sa)) == -1) {
save_errno = errno;
if (ldpd_privs.change(ZPRIVS_LOWER))
log_warn("%s: could not lower privs", __func__);
if (fd == -1)
return (0);
#if HAVE_DECL_TCP_MD5SIG
- memcpy(&su, addr2sa(af, addr, 0), sizeof(su));
+ addr2sa(af, addr, 0, &su);
if (ldpe_privs.change(ZPRIVS_RAISE)) {
log_warn("%s: could not raise privs", __func__);
}
}
-struct sockaddr *
-addr2sa(int af, union ldpd_addr *addr, uint16_t port)
+void
+addr2sa(int af, const union ldpd_addr *addr, uint16_t port, union sockunion *su)
{
- static struct sockaddr_storage ss;
- struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
- struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
+ struct sockaddr_in *sa_in = &su->sin;
+ struct sockaddr_in6 *sa_in6 = &su->sin6;
- memset(&ss, 0, sizeof(ss));
+ memset(su, 0, sizeof(*su));
switch (af) {
case AF_INET:
sa_in->sin_family = AF_INET;
default:
fatalx("addr2sa: unknown af");
}
-
- return ((struct sockaddr *)&ss);
}
void
unsigned int i;
struct hash_backet *hb;
struct hash_backet *hbnext;
- uint32_t count = 0;
- for (i = 0; i < hash->size; i++) {
+ for (i = 0; i < hash->size; i++)
for (hb = hash->index[i]; hb; hb = hbnext) {
/* get pointer to next hash backet here, in case (*func)
* decides to delete hb by calling hash_release
*/
hbnext = hb->next;
(*func)(hb, arg);
- count++;
-
}
- if (count == hash->count)
- return;
- }
}
void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *),
struct hash_backet *hb;
struct hash_backet *hbnext;
int ret = HASHWALK_CONTINUE;
- uint32_t count = 0;
for (i = 0; i < hash->size; i++) {
for (hb = hash->index[i]; hb; hb = hbnext) {
ret = (*func)(hb, arg);
if (ret == HASHWALK_ABORT)
return;
- count++;
}
- if (count == hash->count)
- return;
}
}
* Iterate over the elements in a hash table.
*
* It is safe to delete items passed to the iteration function from the hash
- * table during iteration.
+ * table during iteration. Please note that adding entries to the hash
+ * during the walk will cause undefined behavior in that some new entries
+ * will be walked and some will not. So do not do this.
*
* hash
* hash table to operate on
* Iterate over the elements in a hash table, stopping on condition.
*
* It is safe to delete items passed to the iteration function from the hash
- * table during iteration.
+ * table during iteration. Please note that adding entries to the hash
+ * during the walk will cause undefined behavior in that some new entries
+ * will be walked and some will not. So do not do this.
*
* hash
* hash table to operate on
struct vrf *vrf;
struct interface if_tmp;
- if (vrf_id == VRF_UNKNOWN) {
- struct interface *ifp;
-
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
- if (ifp)
- return ifp;
- }
-
- return NULL;
- }
-
vrf = vrf_lookup_by_id(vrf_id);
if (!vrf)
return NULL;
if (!result) {
if (vty)
- vty_out(vty, "Invalid pathname: %s\n",
+ vty_out(vty, "Invalid pathname for %s: %s\n",
+ pathname,
safe_strerror(errno));
else
- zlog_warn("Invalid pathname: %s", safe_strerror(errno));
+ zlog_warn("Invalid pathname for %s: %s",
+ pathname,
+ safe_strerror(errno));
return NULL;
}
check_base = basename(pathname);
(nhop); \
(nhop) = nexthop_next(nhop)
+#define ALL_NEXTHOPS_PTR(head, nhop) \
+ (nhop) = ((head)->nexthop); \
+ (nhop); \
+ (nhop) = nexthop_next(nhop)
+
struct nexthop_hold {
char *nhvrf_name;
/* NB: read comments in code for refcounting before using! */
static struct route_node *srcdest_srcnode_get(struct route_node *rn,
- struct prefix_ipv6 *src_p)
+ const struct prefix_ipv6 *src_p)
{
struct srcdest_rnode *srn;
route_unlock_node(rn);
}
- return route_node_get(srn->src_table, (struct prefix *)src_p);
+ return route_node_get(srn->src_table, (const struct prefix *)src_p);
}
-static struct route_node *srcdest_srcnode_lookup(struct route_node *rn,
- struct prefix_ipv6 *src_p)
+static struct route_node *srcdest_srcnode_lookup(
+ struct route_node *rn,
+ const struct prefix_ipv6 *src_p)
{
struct srcdest_rnode *srn;
if (!srn->src_table)
return NULL;
- return route_node_lookup(srn->src_table, (struct prefix *)src_p);
+ return route_node_lookup(srn->src_table, (const struct prefix *)src_p);
}
/* ----- exported functions ----- */
}
struct route_node *srcdest_rnode_get(struct route_table *table,
- union prefixptr dst_pu,
- struct prefix_ipv6 *src_p)
+ union prefixconstptr dst_pu,
+ const struct prefix_ipv6 *src_p)
{
- struct prefix_ipv6 *dst_p = dst_pu.p6;
+ const struct prefix_ipv6 *dst_p = dst_pu.p6;
struct route_node *rn;
- rn = route_node_get(table, (struct prefix *)dst_p);
+ rn = route_node_get(table, (const struct prefix *)dst_p);
return srcdest_srcnode_get(rn, src_p);
}
struct route_node *srcdest_rnode_lookup(struct route_table *table,
- union prefixptr dst_pu,
- struct prefix_ipv6 *src_p)
+ union prefixconstptr dst_pu,
+ const struct prefix_ipv6 *src_p)
{
- struct prefix_ipv6 *dst_p = dst_pu.p6;
+ const struct prefix_ipv6 *dst_p = dst_pu.p6;
struct route_node *rn;
struct route_node *srn;
- rn = route_node_lookup_maynull(table, (struct prefix *)dst_p);
+ rn = route_node_lookup_maynull(table, (const struct prefix *)dst_p);
srn = srcdest_srcnode_lookup(rn, src_p);
if (rn != NULL && rn == srn && !rn->info) {
return srn;
}
-void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p,
- struct prefix **src_p)
+void srcdest_rnode_prefixes(struct route_node *rn, const struct prefix **p,
+ const struct prefix **src_p)
{
if (rnode_is_srcnode(rn)) {
struct route_node *dst_rn = rn->table->info;
const char *srcdest_rnode2str(struct route_node *rn, char *str, int size)
{
- struct prefix *dst_p, *src_p;
+ const struct prefix *dst_p, *src_p;
char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN];
srcdest_rnode_prefixes(rn, &dst_p, &src_p);
extern struct route_table *srcdest_table_init(void);
extern struct route_node *srcdest_rnode_get(struct route_table *table,
- union prefixptr dst_pu,
- struct prefix_ipv6 *src_p);
+ union prefixconstptr dst_pu,
+ const struct prefix_ipv6 *src_p);
extern struct route_node *srcdest_rnode_lookup(struct route_table *table,
- union prefixptr dst_pu,
- struct prefix_ipv6 *src_p);
-extern void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p,
- struct prefix **src_p);
+ union prefixconstptr dst_pu,
+ const struct prefix_ipv6 *src_p);
+extern void srcdest_rnode_prefixes(struct route_node *rn,
+ const struct prefix **p,
+ const struct prefix **src_p);
extern const char *srcdest_rnode2str(struct route_node *rn, char *str,
int size);
extern struct route_node *srcdest_route_next(struct route_node *rn);
const char *protocolname;
char *cp = NULL;
+ assert(vty);
+
/*
* Log non empty command lines
*/
/* format the base vty info */
snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address);
- if (vty)
- for (i = 0; i < vector_active(vtyvec); i++)
- if (vty == vector_slot(vtyvec, i)) {
- snprintf(vty_str, sizeof(vty_str),
- "vty[%d]@%s", i, vty->address);
- break;
- }
+
+ for (i = 0; i < vector_active(vtyvec); i++)
+ if (vty == vector_slot(vtyvec, i)) {
+ snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s",
+ i, vty->address);
+ break;
+ }
/* format the prompt */
snprintf(prompt_str, sizeof(prompt_str), cmd_prompt(vty->node),
char yielded = 0;
wq = THREAD_ARG(thread);
- wq->thread = NULL;
assert(wq);
+ wq->thread = NULL;
+
/* calculate cycle granularity:
* list iteration == 1 run
* listnode processing == 1 cycle
buf[len] = 0;
debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
- if (sscanf(buf, "eventid=%d", &eventid) != 1)
+ if (sscanf(buf, "eventid=%" SCNu32, &eventid) != 1)
continue;
if (sscanf(buf, "result=%63s", result) != 1)
continue;
if (!cie)
return NULL;
- if (cie->nbma_address_len + cie->nbma_subaddress_len) {
+ if (cie->nbma_address_len + cie->nbma_subaddress_len > 0) {
sockunion_set(nbma, afi2family(htons(hdr->afnum)),
zbuf_pulln(zb,
cie->nbma_address_len
uint32_t msglen;
uint8_t msgtype;
struct blob name;
- struct vici_message_ctx ctx;
+ struct vici_message_ctx ctx = { .nsections = 0 };
msglen = zbuf_get_be32(msg);
msgtype = zbuf_get8(msg);
struct ospf_route *newor)
{
struct route_node *rn;
- struct ospf_route * or ;
+ struct ospf_route *or;
struct ospf_path *op;
struct ospf_path *newop;
struct listnode *n1;
route_unlock_node(rn);
or = rn->info;
+
+ assert(or);
+
if (or->path_type != newor->path_type)
return 0;
return 0;
}
+ assert(or->paths);
+
if (or->paths->count != newor->paths->count)
return 0;
p.prefix = lsa->data->id;
p.prefixlen = ip_masklen(al->mask);
- for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
int redist_on = 0;
redist_on =
zlog_debug(
"ospf_translated_nssa_refresh(): no Type-7 found for "
"Type-5 LSA Id %s",
- inet_ntoa(type5->data->id));
+ type5 ? inet_ntoa(type5->data->id) : "(null)");
return NULL;
}
zlog_debug(
"ospf_translated_nssa_refresh(): No translated Type-5 "
"found for Type-7 with Id %s",
- inet_ntoa(type7->data->id));
+ type7 ? inet_ntoa(type7->data->id) : "(null)");
return NULL;
}
zlog_debug(
"ospf_translated_nssa_refresh(): Could not translate "
"Type-7 for %s to Type-5",
- inet_ntoa(type7->data->id));
+ type7 ? inet_ntoa(type7->data->id) : "(null)");
return NULL;
}
zlog_debug(
"ospf_translated_nssa_refresh(): Could not install "
"translated LSA, Id %s",
- inet_ntoa(type7->data->id));
+ type7 ? inet_ntoa(type7->data->id) : "(null)");
return NULL;
}
if (!ospf_ri_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
- if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) {
+ if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
}
uint32_t as;
struct ospf_pce_info *pce = &OspfRI.pce_info;
- if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) {
+ if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
vty_out(vty, "no_pce_domain: fscanf: %s\n",
safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
if (!ospf_ri_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
- if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) {
+ if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
vty_out(vty, "pce_neighbor: fscanf: %s\n",
safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
uint32_t as;
struct ospf_pce_info *pce = &OspfRI.pce_info;
- if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) {
+ if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) {
vty_out(vty, "no_pce_neighbor: fscanf: %s\n",
safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
return CMD_SUCCESS;
}
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180708
-CPP_NOTICE("ospf: `timers lsa arrival (0-1000)` deprecated 2017/07/08")
-#endif
-ALIAS_HIDDEN(ospf_timers_lsa_min_arrival, ospf_timers_lsa_arrival_cmd,
- "timers lsa arrival (0-1000)",
- "adjust routing timers\n"
- "throttling link state advertisement delays\n"
- "ospf minimum arrival interval delay\n"
- "delay (msec) between accepted lsas\n");
-
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180708
-CPP_NOTICE("ospf: `no timers lsa arrival (0-1000)` deprecated 2017/07/08")
-#endif
-ALIAS_HIDDEN(no_ospf_timers_lsa_min_arrival, no_ospf_timers_lsa_arrival_cmd,
- "no timers lsa arrival (0-1000)", NO_STR
- "adjust routing timers\n"
- "throttling link state advertisement delays\n"
- "ospf minimum arrival interval delay\n"
- "delay (msec) between accepted lsas\n");
-
-
DEFUN (ospf_neighbor,
ospf_neighbor_cmd,
"neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
vty_out(vty, " Poll interval %d\n", nbr_nbma->v_poll);
/* Show poll-interval timer. */
- if (use_json) {
- long time_store;
- time_store = monotime_until(&nbr_nbma->t_poll->u.sands, NULL)
- / 1000LL;
- json_object_int_add(json_sub, "pollIntervalTimerDueMsec",
- time_store);
- } else
- vty_out(vty, " Poll timer due in %s\n",
- ospf_timer_dump(nbr_nbma->t_poll, timebuf,
- sizeof(timebuf)));
+ if (nbr_nbma->t_poll) {
+ if (use_json) {
+ long time_store;
+ time_store = monotime_until(&nbr_nbma->t_poll->u.sands,
+ NULL) / 1000LL;
+ json_object_int_add(json_sub,
+ "pollIntervalTimerDueMsec",
+ time_store);
+ } else
+ vty_out(vty, " Poll timer due in %s\n",
+ ospf_timer_dump(nbr_nbma->t_poll, timebuf,
+ sizeof(timebuf)));
+ }
/* Show poll-interval timer thread. */
if (use_json) {
install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd);
install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd);
install_element(OSPF_NODE, &no_ospf_timers_lsa_min_arrival_cmd);
- install_element(OSPF_NODE, &ospf_timers_lsa_arrival_cmd);
- install_element(OSPF_NODE, &no_ospf_timers_lsa_arrival_cmd);
/* refresh timer commands */
install_element(OSPF_NODE, &ospf_refresh_timer_cmd);
int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, void *jarg)
{
- int status;
struct sockaddr_nl nladdr;
char buf[8192];
struct nlmsghdr *h = (void *)buf;
nladdr.nl_groups = 0;
while (1) {
- int err, len;
- int l;
+ int err;
+ size_t l, rl, arl;
- status = fread(&buf, 1, sizeof(*h), rtnl);
+ rl = sizeof(*h);
+ arl = fread(&buf, 1, rl, rtnl);
- if (status < 0) {
- if (errno == EINTR)
- continue;
- perror("rtnl_from_file: fread");
+ if (arl != rl) {
+ if (arl == 0)
+ return 0;
+
+ if (ferror(rtnl))
+ fprintf(stderr, "%s: header read failed\n",
+ __func__);
+ else
+ fprintf(stderr, "%s: truncated header\n",
+ __func__);
return -1;
}
- if (status == 0)
- return 0;
- len = h->nlmsg_len;
- l = len - sizeof(*h);
+ l = h->nlmsg_len > rl ? h->nlmsg_len - rl : 0;
- if (l < 0 || len > (int)sizeof(buf)) {
- fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
- len, ftell(rtnl));
+ if (l == 0 || (l + (size_t)NLMSG_HDRLEN) > sizeof(buf)) {
+ fprintf(stderr, "%s: malformed message: len=%zu @%lu\n",
+ __func__, (size_t)h->nlmsg_len, ftell(rtnl));
return -1;
}
- status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
+ rl = NLMSG_ALIGN(l);
+ arl = fread(NLMSG_DATA(h), 1, rl, rtnl);
- if (status < 0) {
- perror("rtnl_from_file: fread");
- return -1;
- }
- if (status < l) {
- fprintf(stderr, "rtnl-from_file: truncated message\n");
+ if (arl != rl) {
+ if (ferror(rtnl))
+ fprintf(stderr, "%s: msg read failed\n",
+ __func__);
+ else
+ fprintf(stderr, "%s: truncated message\n",
+ __func__);
return -1;
}
if (!pim_br) {
pim_br = XCALLOC(MTYPE_PIM_BR, sizeof(*pim_br));
- if (!pim_br) {
- zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br));
- return;
- }
pim_br->sg = *sg;
void pim_br_init(void)
{
pim_br_list = list_new();
- if (!pim_br_list) {
- zlog_err("%s: Failure to create pim_br_list",
- __PRETTY_FUNCTION__);
- return;
- }
}
} else {
vty_out(vty, "%-9d %-15s %-15s %-7s ",
c_oil->installed, src_str, grp_str,
- ifp_in->name);
+ in_ifname);
}
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
return;
}
-static void *if_list_clean(struct pim_interface *pim_ifp)
-{
- struct pim_ifchannel *ch;
-
- if (pim_ifp->igmp_join_list)
- list_delete_and_null(&pim_ifp->igmp_join_list);
-
- if (pim_ifp->igmp_socket_list)
- list_delete_and_null(&pim_ifp->igmp_socket_list);
-
- if (pim_ifp->pim_neighbor_list)
- list_delete_and_null(&pim_ifp->pim_neighbor_list);
-
- if (pim_ifp->upstream_switch_list)
- list_delete_and_null(&pim_ifp->upstream_switch_list);
-
- if (pim_ifp->sec_addr_list)
- list_delete_and_null(&pim_ifp->sec_addr_list);
-
- while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
- ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
-
- pim_ifchannel_delete(ch);
- }
-
- XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
-
- return 0;
-}
-
static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
{
XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
zassert(!ifp->info);
pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
- if (!pim_ifp) {
- zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp));
- return 0;
- }
pim_ifp->options = 0;
pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
/* list of struct igmp_sock */
pim_ifp->igmp_socket_list = list_new();
- if (!pim_ifp->igmp_socket_list) {
- zlog_err("%s: failure: igmp_socket_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
/* list of struct pim_neighbor */
pim_ifp->pim_neighbor_list = list_new();
- if (!pim_ifp->pim_neighbor_list) {
- zlog_err("%s: failure: pim_neighbor_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
pim_ifp->upstream_switch_list = list_new();
- if (!pim_ifp->upstream_switch_list) {
- zlog_err("%s: failure: upstream_switch_list=list_new()",
- __PRETTY_FUNCTION__);
- return if_list_clean(pim_ifp);
- }
pim_ifp->upstream_switch_list->del =
(void (*)(void *))pim_jp_agg_group_list_free;
pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
pim_ifp->sec_addr_list = list_new();
- 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 =
(int (*)(void *, void *))pim_sec_addr_comp;
}
sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
- if (!sec_addr)
- return changed;
changed = 1;
sec_addr->addr = *addr;
}
ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
- if (!ij) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<grp?>", group_addr, group_str,
- sizeof(group_str));
- pim_inet4_dump("<src?>", source_addr, source_str,
- sizeof(source_str));
- zlog_err(
- "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
- __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str,
- ifp->name);
- close(join_fd);
- return 0;
- }
ij->sock_fd = join_fd;
ij->group_addr = group_addr;
if (!pim_ifp->igmp_join_list) {
pim_ifp->igmp_join_list = list_new();
- if (!pim_ifp->igmp_join_list) {
- return ferr_cfg_invalid("Insufficient memory");
- }
pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
}
pim_ifp = ifp->info;
ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch));
- if (!ch) {
- zlog_warn(
- "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s",
- __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
- return NULL;
- }
ch->flags = 0;
if ((source_flags & PIM_ENCODE_RPT_BIT)
}
igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp));
- if (!igmp) {
- zlog_warn("%s %s: XCALLOC() failure", __FILE__,
- __PRETTY_FUNCTION__);
- return 0;
- }
igmp->igmp_group_list = list_new();
- if (!igmp->igmp_group_list) {
- zlog_err("%s %s: failure: igmp_group_list = list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return 0;
- }
igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free;
snprintf(hash_name, 64, "IGMP %s hash", ifp->name);
*/
group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group));
- if (!group) {
- zlog_warn("%s %s: XCALLOC() failure", __FILE__,
- __PRETTY_FUNCTION__);
- return NULL; /* error, not found, could not create */
- }
group->group_source_list = list_new();
- if (!group->group_source_list) {
- zlog_warn("%s %s: list_new() failure", __FILE__,
- __PRETTY_FUNCTION__);
- XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */
- return NULL; /* error, not found, could not initialize */
- }
group->group_source_list->del = (void (*)(void *))igmp_source_free;
group->t_group_timer = NULL;
}
src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src));
- if (!src) {
- zlog_warn("%s %s: XCALLOC() failure", __FILE__,
- __PRETTY_FUNCTION__);
- return 0; /* error, not found, could not create */
- }
src->t_source_timer = NULL;
src->source_group = group; /* back pointer */
char hash_name[64];
pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance));
- if (!pim)
- return NULL;
pim_if_init(pim);
}
pim->static_routes = list_new();
- if (!pim->static_routes) {
- zlog_err("%s %s: failure: static_routes=list_new()", __FILE__,
- __PRETTY_FUNCTION__);
- pim_instance_terminate(pim);
- return NULL;
- }
pim->static_routes->del = (void (*)(void *))pim_static_route_free;
pim->send_v6_secondary = 1;
if (first) {
groups = list_new();
-
jag.sources = list_new();
listnode_add(groups, &jag);
struct pim_rpf *rpg;
struct prefix_sg sg;
- rpg = RP(pim_ifp->pim, msg->im_dst);
+ rpg = pim_ifp ? RP(pim_ifp->pim, msg->im_dst) : NULL;
/*
* If the incoming interface is unknown OR
* the Interface type is SSM we don't need to
* do anything here
*/
- if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
+ if (!rpg || (pim_rpf_addr_is_inaddr_none(rpg))
|| (!(PIM_I_am_DR(pim_ifp)))) {
if (PIM_DEBUG_MROUTE_DETAIL)
zlog_debug(
pim_ifp = up->rpf.source_nexthop.interface->info;
- rpg = RP(pim_ifp->pim, sg.grp);
+ rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
|| (!(PIM_I_am_DR(pim_ifp)))) {
struct pim_msdp_sa *sa;
sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa));
- if (!sa) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*sa));
- return NULL;
- }
sa->pim = pim;
sa->sg = *sg;
pim_msdp_enable(pim);
mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp));
- if (!mp) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*mp));
- return PIM_MSDP_ERR_OOM;
- }
mp->pim = pim;
mp->peer = peer_addr;
struct pim_msdp_mg *mg;
mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg));
- if (!mg) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*mg));
- return NULL;
- }
mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name);
mg->mbr_list = list_new();
}
mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr));
- if (!mbr) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*mbr));
- /* if there are no references to the mg free it */
- pim_msdp_mg_free(pim, mg);
- return PIM_MSDP_ERR_OOM;
- }
mbr->mbr_ip = mbr_ip;
listnode_add_sort(mg->mbr_list, mbr);
zassert(pim_ifp);
neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
- if (!neigh) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*neigh));
- return 0;
- }
neigh->creation = pim_time_monotonic_sec();
neigh->source_addr = source_addr;
pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE,
sizeof(struct pim_nexthop_cache));
- if (!pnc) {
- zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__);
- return NULL;
- }
pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family;
pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen;
pnc->rpf.rpf_addr.u.prefix4.s_addr =
pnc = pim_nexthop_cache_find(pim, &rpf);
if (!pnc) {
pnc = pim_nexthop_cache_add(pim, &rpf);
- if (!pnc) {
- char rpf_str[PREFIX_STRLEN];
- pim_addr_dump("<nht-pnc?>", addr, rpf_str,
- sizeof(rpf_str));
- zlog_warn("%s: pnc node allocation failed. addr %s ",
- __PRETTY_FUNCTION__, rpf_str);
- return 0;
- }
pim_sendmsg_zebra_rnh(pim, zclient, pnc,
ZEBRA_NEXTHOP_REGISTER);
if (PIM_DEBUG_PIM_NHT) {
pim_oil_equal, hash_name);
pim->channel_oil_list = list_new();
- if (!pim->channel_oil_list) {
- zlog_err("%s %s: failure: channel_oil_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return;
- }
pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free;
pim->channel_oil_list->cmp =
(int (*)(void *, void *))pim_channel_oil_compare;
}
c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil));
- if (!c_oil) {
- zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil));
- return NULL;
- }
c_oil->oil.mfcc_mcastgrp = sg->grp;
c_oil->oil.mfcc_origin = sg->src;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
- if (!rp_info) {
- zlog_err("Unable to alloc rp_info");
- route_table_finish(pim->rp_table);
- list_delete_and_null(&pim->rp_list);
- return;
- }
-
if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
zlog_err("Unable to convert 224.0.0.0/4 to prefix");
list_delete_and_null(&pim->rp_list);
struct route_node *rn;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
- if (!rp_info)
- return PIM_MALLOC_FAIL;
if (group_range == NULL)
result = str2prefix("224.0.0.0/4", &rp_info->group);
listnode_add_sort(pim->rp_list, rp_info);
rn = route_node_get(pim->rp_table, &rp_info->group);
- if (!rn) {
- char buf[PREFIX_STRLEN];
- zlog_err("Failure to get route node for pim->rp_table: %s",
- prefix2str(&rp_info->group, buf, sizeof(buf)));
- return PIM_MALLOC_FAIL;
- }
rn->info = rp_info;
if (PIM_DEBUG_TRACE) {
if (!pim->ssmpingd_list) {
pim->ssmpingd_list = list_new();
- if (!pim->ssmpingd_list) {
- zlog_err(
- "%s %s: failure: qpim_ssmpingd_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return 0;
- }
pim->ssmpingd_list->del = (void (*)(void *))ssmpingd_free;
}
}
ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss));
- if (!ss) {
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", source_addr, source_str,
- sizeof(source_str));
- zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s",
- __PRETTY_FUNCTION__, sizeof(*ss), source_str);
- close(sock_fd);
- return 0;
- }
ss->pim = pim;
ss->sock_fd = sock_fd;
static struct static_route *static_route_alloc()
{
- struct static_route *s_route;
-
- s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route));
- if (!s_route) {
- zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route));
- return 0;
- }
- return s_route;
+ return XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(struct static_route));
}
static struct static_route *static_route_new(unsigned int iif, unsigned int oif,
{
struct static_route *s_route;
s_route = static_route_alloc();
- if (!s_route) {
- return 0;
- }
s_route->group = group;
s_route->source = source;
*/
if (!*hello_option_addr_list) {
*hello_option_addr_list = list_new();
- if (!*hello_option_addr_list) {
- zlog_err(
- "%s %s: failure: hello_option_addr_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return -2;
- }
(*hello_option_addr_list)->del =
(void (*)(void *))prefix_free;
}
struct pim_upstream *up;
up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
- if (!up) {
- zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
- sizeof(*up));
- return NULL;
- }
up->sg = *sg;
pim_str_sg_set(sg, up->sg_str);
* If we have a pimreg device callback and it's for a specific
* table set the master appropriately
*/
- if (sscanf(ifp->name, "pimreg%d", &table_id) == 1) {
+ if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) {
struct vrf *vrf;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((table_id == vrf->data.l.table_id)
#################### FRRouting (FRR) configure options #####################
# with-feature options
-%{!?with_pam: %global with_pam 0 }
-%{!?with_ospfclient: %global with_ospfclient 1 }
-%{!?with_ospfapi: %global with_ospfapi 1 }
-%{!?with_rtadv: %global with_rtadv 1 }
-%{!?with_ldpd: %global with_ldpd 1 }
-%{!?with_nhrpd: %global with_nhrpd 1 }
-%{!?with_eigrpd: %global with_eigrpd 1 }
%{!?with_babeld: %global with_babeld 1 }
-%{!?with_shared: %global with_shared 1 }
-%{!?with_multipath: %global with_multipath 256 }
-%{!?frr_user: %global frr_user frr }
-%{!?vty_group: %global vty_group frrvty }
-%{!?with_fpm: %global with_fpm 1 }
-%{!?with_watchfrr: %global with_watchfrr 1 }
%{!?with_bgp_vnc: %global with_bgp_vnc 0 }
+%{!?with_cumulus: %global with_cumulus 0 }
+%{!?with_eigrpd: %global with_eigrpd 1 }
+%{!?with_fpm: %global with_fpm 1 }
+%{!?with_ldpd: %global with_ldpd 1 }
+%{!?with_multipath: %global with_multipath 256 }
+%{!?with_nhrpd: %global with_nhrpd 1 }
+%{!?with_ospfapi: %global with_ospfapi 1 }
+%{!?with_ospfclient: %global with_ospfclient 1 }
+%{!?with_pam: %global with_pam 0 }
+%{!?with_pbrd: %global with_pbrd 1 }
%{!?with_pimd: %global with_pimd 1 }
%{!?with_rpki: %global with_rpki 0 }
-%{!?with_pbrd: %global with_pbrd 1 }
+%{!?with_rtadv: %global with_rtadv 1 }
+%{!?with_watchfrr: %global with_watchfrr 1 }
+
+# user and group
+%{!?frr_user: %global frr_user frr }
+%{!?vty_group: %global vty_group frrvty }
# path defines
-%define _sysconfdir /etc/frr
-%define _sbindir /usr/lib/frr
-%define zeb_src %{_builddir}/%{name}-%{frrversion}
-%define zeb_rh_src %{zeb_src}/redhat
-%define zeb_docs %{zeb_src}/doc
-%define frr_tools %{zeb_src}/tools
+%define configdir %{_sysconfdir}/%{name}
+%define _sbindir /usr/lib/frr
+%define zeb_src %{_builddir}/%{name}-%{frrversion}
+%define zeb_rh_src %{zeb_src}/redhat
+%define zeb_docs %{zeb_src}/doc
+%define frr_tools %{zeb_src}/tools
# defines for configure
-%define _localstatedir /var/run/frr
+%define rundir %{_localstatedir}/run/%{name}
# define for sphinx-build binary
%if 0%{?rhel} && 0%{?rhel} < 7
-%define sphinx sphinx-build2.7
+ %define sphinx sphinx-build2.7
%else
-%define sphinx sphinx-build
+ %define sphinx sphinx-build
%endif
############################################################################
%{!?frr_gid: %global frr_gid 92 }
%{!?vty_gid: %global vty_gid 85 }
-%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd
+%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd
%if %{with_ldpd}
-%define daemon_ldpd ldpd
+ %define daemon_ldpd ldpd
%else
-%define daemon_ldpd ""
+ %define daemon_ldpd ""
%endif
%if %{with_pimd}
-%define daemon_pimd pimd
+ %define daemon_pimd pimd
%else
-%define daemon_pimd ""
+ %define daemon_pimd ""
%endif
%if %{with_pbrd}
-%define daemon_pbrd pbrd
+ %define daemon_pbrd pbrd
%else
-%define daemon_pbrd ""
+ %define daemon_pbrd ""
%endif
%if %{with_nhrpd}
-%define daemon_nhrpd nhrpd
+ %define daemon_nhrpd nhrpd
%else
-%define daemon_nhrpd ""
+ %define daemon_nhrpd ""
%endif
%if %{with_eigrpd}
-%define daemon_eigrpd eigrpd
+ %define daemon_eigrpd eigrpd
%else
-%define daemon_eigrpd ""
+ %define daemon_eigrpd ""
%endif
%if %{with_babeld}
-%define daemon_babeld babeld
+ %define daemon_babeld babeld
%else
-%define daemon_babeld ""
+ %define daemon_babeld ""
%endif
%if %{with_watchfrr}
-%define daemon_watchfrr watchfrr
+ %define daemon_watchfrr watchfrr
%else
-%define daemon_watchfrr ""
+ %define daemon_watchfrr ""
%endif
%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_pimd} %{daemon_nhrpd} %{daemon_eigrpd} %{daemon_babeld} %{daemon_watchfrr} %{daemon_pbrd}
-# allow build dir to be kept
-%{!?keep_build: %global keep_build 0 }
-
#release sub-revision (the two digits after the CONFDATE)
%{!?release_rev: %global release_rev 01 }
Group: System Environment/Daemons
Source0: https://github.com/FRRouting/frr/archive/%{name}-%{frrversion}.tar.gz
URL: https://www.frrouting.org
+Requires(pre): shadow-utils
Requires(preun): info
Requires(post): info
-BuildRequires: gcc patch libcap-devel
-BuildRequires: readline-devel ncurses-devel
-BuildRequires: json-c-devel bison >= 2.7 flex make
-BuildRequires: c-ares-devel texinfo
+BuildRequires: bison >= 2.7
+BuildRequires: c-ares-devel
+BuildRequires: flex
+BuildRequires: gcc
+BuildRequires: json-c-devel
+BuildRequires: libcap-devel
+BuildRequires: make
+BuildRequires: ncurses-devel
+BuildRequires: readline-devel
+BuildRequires: texinfo
%if 0%{?rhel} && 0%{?rhel} < 7
#python27-devel is available from ius community repo for RedHat/CentOS 6
-BuildRequires: python27-devel python27-sphinx
+BuildRequires: python27-devel
+BuildRequires: python27-sphinx
%else
-BuildRequires: python-devel >= 2.7 python-sphinx
+BuildRequires: python-devel >= 2.7
+BuildRequires: python-sphinx
%endif
-Requires: json-c initscripts
%if %{with_pam}
BuildRequires: pam-devel
%endif
BuildRequires: librtr-devel >= 0.5
%endif
%if "%{initsystem}" == "systemd"
-BuildRequires: systemd systemd-devel
+BuildRequires: systemd
+BuildRequires: systemd-devel
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
Requires(preun): chkconfig
# Initscripts > 5.60 is required for IPv6 support
Requires(pre): initscripts >= 5.60
+Requires: initscripts
%endif
Provides: routingdaemon = %{version}-%{release}
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
Obsoletes: gated mrt zebra frr-sysvinit
Conflicts: bird
+
%description
FRRouting is a free software that manages TCP/IP based routing
protocol. It takes multi-server and multi-thread approach to resolve
FRRouting is a fork of Quagga.
+
%package contrib
Summary: contrib tools for frr
Group: System Environment/Daemons
%description contrib
Contributed/3rd party tools which may be of use with frr.
+
%package pythontools
Summary: python tools for frr
BuildRequires: python
%description pythontools
Contributed python 2.7 tools which may be of use with frr.
+
%package devel
Summary: Header and object files for frr development
Group: System Environment/Daemons
The frr-devel package contains the header and object files neccessary for
developing OSPF-API and frr applications.
+
%prep
-%setup -q -n frr-%{frrversion}
+%setup -q -n frr-%{frrversion}
+
%build
%configure \
--sbindir=%{_sbindir} \
- --sysconfdir=%{_sysconfdir} \
- --libdir=%{_libdir} \
- --libexecdir=%{_libexecdir} \
- --localstatedir=%{_localstatedir} \
+ --sysconfdir=%{configdir} \
+ --localstatedir=%{rundir} \
+ --disable-static \
--disable-werror \
--enable-irdp \
-%if !%{with_shared}
- --disable-shared \
-%endif
%if %{with_multipath}
--enable-multipath=%{with_multipath} \
%endif
--with-libpam \
%endif
%if 0%{?frr_user:1}
- --enable-user=%frr_user \
- --enable-group=%frr_user \
+ --enable-user=%{frr_user} \
+ --enable-group=%{frr_user} \
%endif
%if 0%{?vty_group:1}
- --enable-vty-group=%vty_group \
+ --enable-vty-group=%{vty_group} \
%endif
%if %{with_fpm}
--enable-fpm \
%else
--disable-watchfrr \
%endif
+%if %{with_cumulus}
+ --enable-cumulus \
+%endif
%if %{with_bgp_vnc}
--enable-bgp-vnc \
%else
--enable-systemd \
%endif
%if %{with_rpki}
- --enable-rpki \
+ --enable-rpki
+%else
+ --disable-rpki
%endif
- --enable-poll
make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" SPHINXBUILD=%{sphinx}
make SPHINXBUILD=%{sphinx} info
popd
+
%install
-mkdir -p %{buildroot}/etc/{frr,sysconfig,logrotate.d,pam.d,default} \
- %{buildroot}/var/log/frr %{buildroot}%{_infodir}
+mkdir -p %{buildroot}%{_sysconfdir}/{frr,sysconfig,logrotate.d,pam.d,default} \
+ %{buildroot}%{_localstatedir}/log/frr %{buildroot}%{_infodir}
make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" SPHINXBUILD=%{sphinx} install
# Remove this file, as it is uninstalled and causes errors when building on RH9
# Remove debian init script if it was installed
rm -f %{buildroot}%{_sbindir}/frr
-# kill bogus libtool files for modules
-rm -f %{buildroot}%{_libdir}/frr/modules/*.la
+# kill bogus libtool files
+rm -vf %{buildroot}%{_libdir}/frr/modules/*.la
+rm -vf %{buildroot}%{_libdir}/*.la
# install /etc sources
%if "%{initsystem}" == "systemd"
mkdir -p %{buildroot}%{_unitdir}
-install -m644 %{zeb_rh_src}/frr.service \
- %{buildroot}%{_unitdir}/frr.service
-install %{zeb_rh_src}/frr.init \
- %{buildroot}%{_sbindir}/frr
+install -m644 %{zeb_rh_src}/frr.service %{buildroot}%{_unitdir}/frr.service
+install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
%else
-mkdir -p %{buildroot}/etc/rc.d/init.d
-install %{zeb_rh_src}/frr.init \
- %{buildroot}%{_sbindir}/frr
-ln -s %{_sbindir}/frr \
- %{buildroot}/etc/rc.d/init.d/frr
+mkdir -p %{buildroot}%{_initddir}
+install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
+ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr
%endif
-install %{zeb_rh_src}/daemons %{buildroot}/etc/frr
-install -m644 %{zeb_rh_src}/frr.pam \
- %{buildroot}/etc/pam.d/frr
-install -m644 %{zeb_rh_src}/frr.logrotate \
- %{buildroot}/etc/logrotate.d/frr
-install -d -m750 %{buildroot}/var/run/frr
+install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr
+install -m644 %{zeb_rh_src}/frr.pam %{buildroot}%{_sysconfdir}/pam.d/frr
+install -m644 %{zeb_rh_src}/frr.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/frr
+install -d -m750 %{buildroot}%{rundir}
+
%pre
# add vty_group
%if 0%{?vty_group:1}
-if getent group %vty_group > /dev/null ; then : ; else \
- /usr/sbin/groupadd -r -g %vty_gid %vty_group > /dev/null || : ; fi
+ getent group %{vty_group} >/dev/null || groupadd -r -g %{vty_gid} %{vty_group}
%endif
# add frr user and group
%if 0%{?frr_user:1}
-# Ensure that frr_gid gets correctly allocated
-if getent group %frr_user >/dev/null; then : ; else \
- /usr/sbin/groupadd -g %frr_gid %frr_user > /dev/null || : ; \
-fi
-if getent passwd %frr_user >/dev/null ; then : ; else \
- /usr/sbin/useradd -u %frr_uid -g %frr_gid \
- -M -r -s /sbin/nologin -c "FRRouting suite" \
- -d %_localstatedir %frr_user 2> /dev/null || : ; \
-fi
-%if 0%{?vty_group:1}
-/usr/sbin/usermod -a -G %vty_group %frr_user
-%endif
+ # Ensure that frr_gid gets correctly allocated
+ getent group %{frr_user} >/dev/null || groupadd -g %{frr_gid} %{frr_user}
+ getent passwd %{frr_user} >/dev/null || \
+ useradd -r -u %{frr_uid} -g %{frr_user} \
+ -s /sbin/nologin -c "FRRouting suite" \
+ -d %{rundir} %{frr_user}
+
+ %if 0%{?vty_group:1}
+ usermod -a -G %{vty_group} %{frr_user}
+ %endif
%endif
+exit 0
%post
zebra_spec_add_service ()
{
# Add port /etc/services entry if it isn't already there
- if [ -f /etc/services ] && \
- ! %__sed -e 's/#.*$//' /etc/services | %__grep -wq $1 ; then
- echo "$1 $2 # $3" >> /etc/services
+ if [ -f %{_sysconfdir}/services ] && \
+ ! %__sed -e 's/#.*$//' %{_sysconfdir}/services | %__grep -wq $1 ; then
+ echo "$1 $2 # $3" >> %{_sysconfdir}/services
fi
}
zebra_spec_add_service ospfd 2604/tcp "OSPFd vty"
zebra_spec_add_service bgpd 2605/tcp "BGPd vty"
zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty"
+zebra_spec_add_service isisd 2608/tcp "ISISd vty"
%if %{with_ospfapi}
-zebra_spec_add_service ospfapi 2607/tcp "OSPF-API"
+ zebra_spec_add_service ospfapi 2607/tcp "OSPF-API"
%endif
-zebra_spec_add_service isisd 2608/tcp "ISISd vty"
%if %{with_babeld}
-zebra_spec_add_service babeld 2609/tcp "BABELd vty"
+ zebra_spec_add_service babeld 2609/tcp "BABELd vty"
%endif
%if %{with_nhrpd}
-zebra_spec_add_service nhrpd 2610/tcp "NHRPd vty"
+ zebra_spec_add_service nhrpd 2610/tcp "NHRPd vty"
%endif
%if %{with_pimd}
-zebra_spec_add_service pimd 2611/tcp "PIMd vty"
+ zebra_spec_add_service pimd 2611/tcp "PIMd vty"
%endif
%if %{with_pbrd}
-zebra_spec_add_service pbrd 2615/tcp "PBRd vty"
+ zebra_spec_add_service pbrd 2615/tcp "PBRd vty"
%endif
%if %{with_ldpd}
-zebra_spec_add_service ldpd 2612/tcp "LDPd vty"
+ zebra_spec_add_service ldpd 2612/tcp "LDPd vty"
%endif
%if %{with_eigrpd}
-zebra_spec_add_service eigrpd 2613/tcp "EIGRPd vty"
+ zebra_spec_add_service eigrpd 2613/tcp "EIGRPd vty"
%endif
%if "%{initsystem}" == "systemd"
-for daemon in %all_daemons ; do
- %systemd_post frr.service
-done
+ for daemon in %all_daemons ; do
+ %systemd_post frr.service
+ done
%else
-/sbin/chkconfig --add frr
+ /sbin/chkconfig --add frr
%endif
# Fix bad path in previous config files
# Config files won't get replaced by default, so we do this ugly hack to fix it
-%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{_sysconfdir}/daemons 2> /dev/null || true
+%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{configdir}/daemons 2> /dev/null || true
# With systemd, watchfrr is mandatory. Fix config to make sure it's enabled if
# we install or upgrade to a frr built with systemd
%if "%{initsystem}" == "systemd"
- %__sed -i 's|watchfrr_enable=no|watchfrr_enable=yes|g' %{_sysconfdir}/daemons 2> /dev/null || true
+ %__sed -i 's|watchfrr_enable=no|watchfrr_enable=yes|g' %{configdir}/daemons 2> /dev/null || true
%endif
/sbin/install-info %{_infodir}/frr.info.gz %{_infodir}/dir
# Create dummy files if they don't exist so basic functions can be used.
-if [ ! -e %{_sysconfdir}/zebra.conf ]; then
- echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf
+if [ ! -e %{configdir}/zebra.conf ]; then
+ echo "hostname `hostname`" > %{configdir}/zebra.conf
%if 0%{?frr_user:1}
- chown %frr_user:%frr_user %{_sysconfdir}/zebra.conf*
+ chown %{frr_user}:%{frr_user} %{configdir}/zebra.conf*
%endif
- chmod 640 %{_sysconfdir}/zebra.conf*
+ chmod 640 %{configdir}/zebra.conf*
fi
for daemon in %{all_daemons} ; do
if [ x"${daemon}" != x"" ] ; then
- if [ ! -e %{_sysconfdir}/${daemon}.conf ]; then
- touch %{_sysconfdir}/${daemon}.conf
+ if [ ! -e %{configdir}/${daemon}.conf ]; then
+ touch %{configdir}/${daemon}.conf
%if 0%{?frr_user:1}
- chown %frr_user:%frr_user %{_sysconfdir}/${daemon}.conf*
+ chown %{frr_user}:%{frr_user} %{configdir}/${daemon}.conf*
%endif
fi
fi
done
%if 0%{?frr_user:1}
- chown %frr_user:%frr_user %{_sysconfdir}/daemons
+ chown %{frr_user}:%{frr_user} %{configdir}/daemons
%endif
%if %{with_watchfrr}
# No config for watchfrr - this is part of /etc/sysconfig/frr
- rm -f %{_sysconfdir}/watchfrr.*
+ rm -f %{configdir}/watchfrr.*
%endif
-if [ ! -e %{_sysconfdir}/vtysh.conf ]; then
- touch %{_sysconfdir}/vtysh.conf
- chmod 640 %{_sysconfdir}/vtysh.conf
+if [ ! -e %{configdir}/vtysh.conf ]; then
+ touch %{configdir}/vtysh.conf
+ chmod 640 %{configdir}/vtysh.conf
%if 0%{?frr_user:1}
-%if 0%{?vty_group:1}
- chown %{frr_user}:%{vty_group} %{_sysconfdir}/vtysh.conf*
-%endif
+ %if 0%{?vty_group:1}
+ chown %{frr_user}:%{vty_group} %{configdir}/vtysh.conf*
+ %endif
%endif
fi
+
%postun
if [ "$1" -ge 1 ]; then
#
##
## init.d Version
##
- /etc/rc.d/init.d/frr restart >/dev/null 2>&1
+ service frr restart >/dev/null 2>&1
%endif
:
fi
+
%preun
%if "%{initsystem}" == "systemd"
##
## init.d Version
##
if [ $1 -eq 0 ] ; then
- /etc/rc.d/init.d/frr stop >/dev/null 2>&1
+ service frr stop >/dev/null 2>&1
/sbin/chkconfig --del frr
fi
%endif
/sbin/install-info --delete %{_infodir}/frr.info.gz %{_infodir}/dir
-%clean
-%if !0%{?keep_build:1}
-rm -rf %{buildroot}
-%endif
%files
-%defattr(-,root,root)
%doc */*.sample* AUTHORS COPYING
%doc doc/mpls
%doc ChangeLog NEWS README
%if 0%{?frr_user:1}
-%dir %attr(751,%frr_user,%frr_user) %{_sysconfdir}
-%dir %attr(750,%frr_user,%frr_user) /var/log/frr
-%dir %attr(751,%frr_user,%frr_user) /var/run/frr
+ %dir %attr(751,%{frr_user},%{frr_user}) %{configdir}
+ %dir %attr(750,%{frr_user},%{frr_user}) %{_localstatedir}/log/frr
+ %dir %attr(751,%{frr_user},%{frr_user}) %{rundir}
%else
-%dir %attr(750,root,root) %{_sysconfdir}
-%dir %attr(750,root,root) /var/log/frr
-%dir %attr(750,root,root) /var/run/frr
+ %dir %attr(750,root,root) %{configdir}
+ %dir %attr(750,root,root) %{_localstatedir}/log/frr
+ %dir %attr(750,root,root) %{rundir}
%endif
%if 0%{?vty_group:1}
-%attr(750,%frr_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample
+ %attr(750,%{frr_user},%{vty_group}) %{configdir}/vtysh.conf.sample
%endif
%{_infodir}/frr.info.gz
%{_mandir}/man*/*
%if %{with_babeld}
%{_sbindir}/babeld
%endif
-%if %{with_shared}
-%{_libdir}/lib*.so
%{_libdir}/lib*.so.0
-%attr(755,root,root) %{_libdir}/lib*.so.0.*
-%endif
+%{_libdir}/lib*.so.0.*
%if %{with_fpm}
-%attr(755,root,root) %{_libdir}/frr/modules/zebra_fpm.so
+ %{_libdir}/frr/modules/zebra_fpm.so
%endif
%if %{with_rpki}
-%attr(755,root,root) %{_libdir}/frr/modules/bgpd_rpki.so
+ %{_libdir}/frr/modules/bgpd_rpki.so
%endif
-%attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so
+%{_libdir}/frr/modules/zebra_irdp.so
%{_bindir}/*
-%config(noreplace) /etc/frr/[!v]*.conf*
-%config(noreplace) %attr(750,%frr_user,%frr_user) /etc/frr/daemons
+%config(noreplace) %{configdir}/[!v]*.conf*
+%config(noreplace) %attr(750,%{frr_user},%{frr_user}) %{configdir}/daemons
%if "%{initsystem}" == "systemd"
%{_unitdir}/frr.service
%else
- /etc/rc.d/init.d/frr
+ %{_initddir}/frr
%endif
%{_sbindir}/frr
-%config(noreplace) /etc/pam.d/frr
-%config(noreplace) /etc/logrotate.d/frr
+%config(noreplace) %{_sysconfdir}/pam.d/frr
+%config(noreplace) %{_sysconfdir}/logrotate.d/frr
%{_sbindir}/frr-reload
+
%files contrib
-%defattr(-,root,root)
%doc tools
+
%files pythontools
-%defattr(-,root,root)
%{_sbindir}/frr-reload.py
%{_sbindir}/frr-reload.pyc
%{_sbindir}/frr-reload.pyo
+
%files devel
-%defattr(-,root,root)
+%{_libdir}/lib*.so
%if %{with_ospfclient}
-%{_sbindir}/ospfclient
-%endif
-%{_libdir}/*.a
-%{_libdir}/*.la
-%dir %attr(755,root,root) %{_includedir}/%{name}
-%{_includedir}/%name/*.h
-%dir %attr(755,root,root) %{_includedir}/%{name}/ospfd
-%{_includedir}/%name/ospfd/*.h
+ %{_sbindir}/ospfclient
+%endif
+%dir %{_includedir}/%{name}
+%{_includedir}/%{name}/*.h
+%dir %{_includedir}/%{name}/ospfd
+%{_includedir}/%{name}/ospfd/*.h
%if %{with_ospfapi}
-%dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi
-%{_includedir}/%name/ospfapi/*.h
+ %dir %{_includedir}/%{name}/ospfapi
+ %{_includedir}/%{name}/ospfapi/*.h
%endif
%if %{with_eigrpd}
-%dir %attr(755,root,root) %{_includedir}/%{name}/eigrpd
-%{_includedir}/%name/eigrpd/*.h
+ %dir %{_includedir}/%{name}/eigrpd
+ %{_includedir}/%{name}/eigrpd/*.h
%endif
+
%changelog
-* Sun May 20 2018 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+* Sun May 20 2018 Martin Winter <mwinter@opensourcerouting.org>
- Fixed RPKI RPM build
* Sun Mar 4 2018 Martin Winter <mwinter@opensourcerouting.org>
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
struct prefix *p;
- struct route_node *node;
+ struct route_node *n;
p = connected->address;
address.prefix = p->u.prefix6;
address.prefixlen = IPV6_MAX_BITLEN;
- node = route_node_match(ripng_enable_network,
- (struct prefix *)&address);
- if (node) {
- route_unlock_node(node);
+ n = route_node_match(ripng_enable_network,
+ (struct prefix *)&address);
+ if (n) {
+ route_unlock_node(n);
return 1;
}
}
}
/* Write routing table entry. */
- if (!nexthop)
+ if (!nexthop) {
+ assert(p);
stream_write(s, (uint8_t *)&p->prefix, sizeof(struct in6_addr));
- else
+ } else
stream_write(s, (uint8_t *)nexthop, sizeof(struct in6_addr));
stream_putw(s, tag);
if (p)
__pycache__
.pytest_cache
/bgpd/test_aspath
+/bgpd/test_bgp_table
/bgpd/test_capability
/bgpd/test_ecommunity
/bgpd/test_mp_attr
bgpd/test_peer_attr \
bgpd/test_ecommunity \
bgpd/test_mp_attr \
- bgpd/test_mpath
+ bgpd/test_mpath \
+ bgpd/test_bgp_table
else
TESTS_BGPD =
endif
bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
+bgpd_test_bgp_table_SOURCES = bgpd/test_bgp_table.c
isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h
BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h
bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD)
isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
--- /dev/null
+/*
+ * BGP Routing table range lookup test
+ * Copyright (C) 2012 OSR.
+ * Copyright (C) 2018 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW
+ * Hamburg
+ *
+ * This file is part of FRRouting
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "table.h"
+#include "bgpd/bgp_table.h"
+#include "linklist.h"
+
+/*
+ * test_node_t
+ *
+ * Information that is kept for each node in the radix tree.
+ */
+struct test_node_t {
+
+ /*
+ * Human readable representation of the string. Allocated using
+ * malloc()/dup().
+ */
+ char *prefix_str;
+};
+
+/*
+ * add_node
+ *
+ * Add the given prefix (passed in as a string) to the given table.
+ */
+static void add_node(struct bgp_table *table, const char *prefix_str)
+{
+ struct prefix_ipv4 p;
+ struct test_node_t *node;
+ struct bgp_node *rn;
+
+ assert(prefix_str);
+
+ if (str2prefix_ipv4(prefix_str, &p) <= 0)
+ assert(0);
+
+ rn = bgp_node_get(table, (struct prefix *)&p);
+ if (rn->info) {
+ assert(0);
+ return;
+ }
+
+ node = malloc(sizeof(struct test_node_t));
+ assert(node);
+ node->prefix_str = strdup(prefix_str);
+ assert(node->prefix_str);
+ rn->info = node;
+}
+
+static void print_range_result(struct list *list)
+{
+
+ struct listnode *listnode;
+ struct bgp_node *bnode;
+
+ for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
+ char buf[PREFIX2STR_BUFFER];
+
+ prefix2str(&bnode->p, buf, PREFIX2STR_BUFFER);
+ printf("%s\n", buf);
+ }
+}
+
+static void check_lookup_result(struct list *list, va_list arglist)
+{
+ char *prefix_str;
+ unsigned int prefix_count = 0;
+
+ printf("Searching results\n");
+ while ((prefix_str = va_arg(arglist, char *))) {
+ struct listnode *listnode;
+ struct bgp_node *bnode;
+ struct prefix p;
+ bool found = false;
+
+ prefix_count++;
+ printf("Searching for %s\n", prefix_str);
+
+ if (str2prefix(prefix_str, &p) <= 0)
+ assert(0);
+
+ for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
+ if (prefix_same(&bnode->p, &p))
+ found = true;
+ }
+
+ assert(found);
+ }
+
+ printf("Checking for unexpected result items\n");
+ printf("Expecting %d found %d\n", prefix_count, listcount(list));
+ assert(prefix_count == listcount(list));
+}
+
+static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen,
+ ...)
+{
+ va_list arglist;
+ struct list *list = list_new();
+ struct prefix p;
+
+ list->del = (void (*)(void *))bgp_unlock_node;
+
+ va_start(arglist, maxlen);
+ printf("\nDoing lookup for %s-%d\n", prefix, maxlen);
+ if (str2prefix(prefix, &p) <= 0)
+ assert(0);
+ bgp_table_range_lookup(table, &p, maxlen, list);
+ print_range_result(list);
+
+ check_lookup_result(list, arglist);
+
+ list_delete_and_null(&list);
+
+ va_end(arglist);
+
+ printf("Checks successfull\n");
+}
+
+/*
+ * test_range_lookup
+ */
+static void test_range_lookup(void)
+{
+ struct bgp_table *table = bgp_table_init(NULL, AFI_IP, SAFI_UNICAST);
+
+ printf("Testing bgp_table_range_lookup\n");
+
+ printf("Setup bgp_table");
+ const char *prefixes[] = {"1.16.0.0/16", "1.16.128.0/18",
+ "1.16.192.0/18", "1.16.64.0/19",
+ "1.16.160.0/19", "1.16.32.0/20",
+ "1.16.32.0/21", "16.0.0.0/16"};
+
+ int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+
+ for (int i = 0; i < num_prefixes; i++)
+ add_node(table, prefixes[i]);
+
+ do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL);
+ do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+ "1.16.160.0/19", NULL);
+
+ do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+ "1.16.160.0/19", NULL);
+
+ do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18",
+ "1.16.192.0/18", NULL);
+
+ do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18",
+ "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
+ "1.16.32.0/20", "1.16.32.0/21", NULL);
+
+ do_test(table, "1.17.0.0/16", 20, NULL);
+
+ do_test(table, "128.0.0.0/8", 16, NULL);
+
+ do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL);
+
+ do_test(table, "0.0.0.0/3", 21, "1.16.0.0/16", "1.16.128.0/18",
+ "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
+ "1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL);
+}
+
+int main(void)
+{
+ test_range_lookup();
+}
--- /dev/null
+import frrtest
+
+class TestTable(frrtest.TestMultiOut):
+ program = './test_bgp_table'
+
+for i in range(6):
+ TestTable.onesimple('Checks successfull')
}
static void test_failed(struct test_state *test, const char *message,
- struct prefix_ipv6 *dst_p, struct prefix_ipv6 *src_p)
+ const struct prefix_ipv6 *dst_p,
+ const struct prefix_ipv6 *src_p)
{
char *route_id = format_srcdest(dst_p, src_p);
/* Verify that there are no elements in the table which have never
* been added */
for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) {
- struct prefix_ipv6 *dst_p, *src_p;
+ const struct prefix_ipv6 *dst_p, *src_p;
/* While we are iterating, we hold a lock on the current
* route_node,
expected_lock++;
if (rn->lock != expected_lock) {
- struct prefix_ipv6 *dst_p, *src_p;
+ const struct prefix_ipv6 *dst_p, *src_p;
srcdest_rnode_prefixes(
- rn, (struct prefix **)&dst_p,
- (struct prefix **)&src_p);
+ rn, (const struct prefix **)&dst_p,
+ (const struct prefix **)&src_p);
test_failed(
test,
assert(rn->info == (void *)0xdeadbeef);
- srcdest_rnode_prefixes(rn, (struct prefix **)&dst_p,
- (struct prefix **)&src_p);
+ srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p,
+ (const struct prefix **)&src_p);
memcpy(&hash_entry[0], dst_p, sizeof(*dst_p));
if (src_p)
memcpy(&hash_entry[1], src_p, sizeof(*src_p));
which_route = prng_rand(prng) % test->log->count;
struct route_node *rn;
- struct prefix *dst_p, *src_p;
+ const struct prefix *dst_p, *src_p;
struct prefix_ipv6 dst6_p, src6_p;
for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) {
if (broad) {
memset(&d, 0, sizeof(struct prefix));
d.family = AF_INET6;
- IPV6_ADDR_COPY(&d.u.prefix, broad);
+ IPV6_ADDR_COPY(&d.u.prefix6, broad);
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, &p, &d);
} else
}
}
-int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data,
- unsigned int alen)
+int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
+ const void *data, unsigned int alen)
{
int len;
struct rtattr *rta;
return 0;
}
-int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data,
- unsigned int alen)
+int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
+ const void *data, unsigned int alen)
{
unsigned int len;
struct rtattr *subrta;
n->nlmsg_seq = ++nl->seq;
n->nlmsg_pid = nl->snl.nl_pid;
- /* Request an acknowledgement by setting NLM_F_ACK */
- n->nlmsg_flags |= NLM_F_ACK;
-
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x",
snprintf(zns->netlink.name, sizeof(zns->netlink.name),
"netlink-listen (NS %u)", zns->ns_id);
zns->netlink.sock = -1;
- netlink_socket(&zns->netlink, groups, zns->ns_id);
+ if (netlink_socket(&zns->netlink, groups, zns->ns_id) < 0) {
+ zlog_err("Failure to create %s socket",
+ zns->netlink.name);
+ exit(-1);
+ }
snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
"netlink-cmd (NS %u)", zns->ns_id);
zns->netlink_cmd.sock = -1;
- netlink_socket(&zns->netlink_cmd, 0, zns->ns_id);
+ if (netlink_socket(&zns->netlink_cmd, 0, zns->ns_id) < 0) {
+ zlog_err("Failure to create %s socket",
+ zns->netlink_cmd.name);
+ exit(-1);
+ }
/*
* SOL_NETLINK is not available on all platforms yet
#endif
/* Register kernel socket. */
- if (zns->netlink.sock > 0) {
- /* Only want non-blocking on the netlink event socket */
- if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
- zlog_err("Can't set %s socket flags: %s",
- zns->netlink.name, safe_strerror(errno));
-
- /* Set receive buffer size if it's set from command line */
- if (nl_rcvbufsize)
- netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
-
- netlink_install_filter(zns->netlink.sock,
- zns->netlink_cmd.snl.nl_pid);
- zns->t_netlink = NULL;
-
- thread_add_read(zebrad.master, kernel_read, zns,
- zns->netlink.sock, &zns->t_netlink);
- }
+ if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
+ zlog_err("Can't set %s socket error: %s(%d)",
+ zns->netlink.name, safe_strerror(errno), errno);
+
+ if (fcntl(zns->netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0)
+ zlog_err("Can't set %s socket error: %s(%d)",
+ zns->netlink_cmd.name, safe_strerror(errno), errno);
+
+ /* Set receive buffer size if it's set from command line */
+ if (nl_rcvbufsize)
+ netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
+
+ netlink_install_filter(zns->netlink.sock,
+ zns->netlink_cmd.snl.nl_pid);
+ zns->t_netlink = NULL;
+
+ thread_add_read(zebrad.master, kernel_read, zns,
+ zns->netlink.sock, &zns->t_netlink);
rt_netlink_init();
}
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
struct rtattr *rta, int len);
extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
- void *data, unsigned int alen);
+ const void *data, unsigned int alen);
extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
- void *data, unsigned int alen);
+ const void *data, unsigned int alen);
extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type,
uint16_t data);
extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type,
for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
RNODE_FOREACH_RE (rn, newre) {
- struct prefix *dst_p, *src_p;
+ const struct prefix *dst_p, *src_p;
char buf[PREFIX_STRLEN];
srcdest_rnode_prefixes(rn, &dst_p, &src_p);
/* Either advertise a route for redistribution to registered clients or */
/* withdraw redistribution if add cannot be done for client */
-void redistribute_update(struct prefix *p, struct prefix *src_p,
+void redistribute_update(const struct prefix *p, const struct prefix *src_p,
struct route_entry *re, struct route_entry *prev_re)
{
struct listnode *node, *nnode;
}
}
-void redistribute_delete(struct prefix *p, struct prefix *src_p,
+void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
struct route_entry *re)
{
struct listnode *node, *nnode;
__func__, zebra_route_string(client->proto), afi,
zebra_route_string(type), zvrf_id(zvrf), instance);
- if (afi == 0 || afi > AFI_MAX) {
+ if (afi == 0 || afi >= AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist",
__PRETTY_FUNCTION__, afi);
return;
STREAM_GETC(msg, type);
STREAM_GETW(msg, instance);
- if (afi == 0 || afi > AFI_MAX) {
+ if (afi == 0 || afi >= AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist",
__PRETTY_FUNCTION__, afi);
return;
extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
/* ----------------- */
-extern void redistribute_update(struct prefix *, struct prefix *,
+extern void redistribute_update(const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *, struct route_entry *);
-extern void redistribute_delete(struct prefix *, struct prefix *,
+extern void redistribute_delete(const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *);
extern void zebra_interface_up_update(struct interface *);
extern int is_zebra_valid_kernel_table(uint32_t table_id);
extern int is_zebra_main_routing_table(uint32_t table_id);
-extern int zebra_check_addr(struct prefix *p);
+extern int zebra_check_addr(const struct prefix *p);
extern void rib_addnode(struct route_node *rn, struct route_entry *re,
int process);
* a re-add.
*/
extern enum dp_req_result kernel_route_rib(struct route_node *rn,
- struct prefix *p,
- struct prefix *src_p,
+ const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *old,
struct route_entry *new);
* so let's separate it out and allow the result to
* be passed back up.
*/
-extern void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
+extern void kernel_route_rib_pass_fail(struct route_node *rn,
+ const struct prefix *p,
struct route_entry *re,
enum dp_results res);
memcpy(&nh.gate, gate, sz);
if (index) {
- ifp = if_lookup_by_index(index, VRF_UNKNOWN);
+ ifp = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(ns_id),
+ index);
if (ifp)
nh_vrf_id = ifp->vrf_id;
}
* using the last one looked
* up right now
*/
- ifp = if_lookup_by_index(index,
- VRF_UNKNOWN);
+ ifp = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(ns_id),
+ index);
if (ifp)
nh_vrf_id = ifp->vrf_id;
else {
* @param zvrf: The vrf we are in
* @param tableid: The table we are working on
*/
-static void _netlink_route_debug(int cmd, struct prefix *p,
- int family, struct zebra_vrf *zvrf,
+static void _netlink_route_debug(int cmd, const struct prefix *p,
+ int family, vrf_id_t vrfid,
uint32_t tableid)
{
if (IS_ZEBRA_DEBUG_KERNEL) {
"netlink_route_multipath(): %s %s vrf %u(%u)",
nl_msg_type_to_str(cmd),
prefix2str(p, buf, sizeof(buf)),
- zvrf_id(zvrf), tableid);
+ vrfid, tableid);
}
}
/* Routing table change via netlink interface. */
/* Update flag indicates whether this is a "replace" or not. */
-static int netlink_route_multipath(int cmd, struct prefix *p,
- struct prefix *src_p, struct route_entry *re,
+static int netlink_route_multipath(int cmd, const struct prefix *p,
+ const struct prefix *src_p,
+ struct route_entry *re,
int update)
{
int bytelen;
addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
}
- _netlink_route_debug(cmd, p, family, zvrf, re->table);
+ _netlink_route_debug(cmd, p, family, zvrf_id(zvrf), re->table);
/*
* If we are not updating the route and we have received
}
enum dp_req_result kernel_route_rib(struct route_node *rn,
- struct prefix *p,
- struct prefix *src_p,
+ const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *old,
struct route_entry *new)
{
}
enum dp_req_result kernel_route_rib(struct route_node *rn,
- struct prefix *p,
- struct prefix *src_p,
+ const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *old,
struct route_entry *new)
{
/* Create entry for neighbor if not known. */
p.family = AF_INET6;
- IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr);
+ IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
p.prefixlen = IPV6_MAX_PREFIXLEN;
if (!nbr_connected_check(ifp, &p))
struct prefix p;
p.family = AF_INET6;
- IPV6_ADDR_COPY(&p.u.prefix, address);
+ IPV6_ADDR_COPY(&p.u.prefix6, address);
p.prefixlen = IPV6_MAX_PREFIXLEN;
ifc = listnode_head(ifp->nbr_connected);
struct prefix p;
p.family = AF_INET6;
- IPV6_ADDR_COPY(&p.u.prefix, address);
+ IPV6_ADDR_COPY(&p.u.prefix6, address);
p.prefixlen = IPV6_MAX_PREFIXLEN;
ifc = nbr_connected_check(ifp, &p);
return zserv_send_message(client, s);
}
-int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
- struct prefix *src_p, struct route_entry *re)
+int zsend_redistribute_route(int cmd, struct zserv *client,
+ const struct prefix *p,
+ const struct prefix *src_p, struct route_entry *re)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
return zserv_send_message(client, s);
}
-int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
- enum zapi_route_notify_owner note)
+/*
+ * Common utility send route notification, called from a path using a
+ * route_entry and from a path using a dataplane context.
+ */
+static int route_notify_internal(const struct prefix *p, int type,
+ uint16_t instance, vrf_id_t vrf_id,
+ uint32_t table_id,
+ enum zapi_route_notify_owner note)
{
struct zserv *client;
struct stream *s;
uint8_t blen;
- client = zserv_find_client(re->type, re->instance);
+ client = zserv_find_client(type, instance);
if (!client || !client->notify_owner) {
if (IS_ZEBRA_DEBUG_PACKET) {
char buff[PREFIX_STRLEN];
zlog_debug(
"Not Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note, re->vrf_id);
+ type, prefix2str(p, buff, sizeof(buff)),
+ table_id, note, vrf_id);
}
return 0;
}
char buff[PREFIX_STRLEN];
zlog_debug("Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
- re->type, prefix2str(p, buff, sizeof(buff)),
- re->table, note, re->vrf_id);
+ type, prefix2str(p, buff, sizeof(buff)),
+ table_id, note, vrf_id);
}
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
- zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
+ zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id);
stream_put(s, ¬e, sizeof(note));
stream_putc(s, p->prefixlen);
stream_put(s, &p->u.prefix, blen);
- stream_putl(s, re->table);
+ stream_putl(s, table_id);
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}
+int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
+ enum zapi_route_notify_owner note)
+{
+ return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
+ re->table, note));
+}
+
void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
enum zapi_rule_notify_owner note)
{
STREAM_GETL(s, ifindex);
if (ifindex) {
- zpr.ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN);
+ zpr.ifp = if_lookup_by_index_per_ns(
+ zvrf->zns,
+ ifindex);
if (!zpr.ifp) {
zlog_debug("Failed to lookup ifindex: %u",
ifindex);
extern int zsend_interface_update(int cmd, struct zserv *client,
struct interface *ifp);
extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
- struct prefix *p, struct prefix *src_p,
+ const struct prefix *p,
+ const struct prefix *src_p,
struct route_entry *re);
extern int zsend_router_id_update(struct zserv *zclient, struct prefix *p,
vrf_id_t vrf_id);
extern int zsend_interface_link_params(struct zserv *zclient,
struct interface *ifp);
extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
-extern int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
+extern int zsend_route_notify_owner(struct route_entry *re,
+ const struct prefix *p,
enum zapi_route_notify_owner note);
extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
#include "zebra/rib.h"
#include "zebra/rt.h"
+#include "zebra/interface.h"
#include "zebra/zserv.h"
#include "zebra/redistribute.h"
#include "zebra/debug.h"
{
struct nexthop *nexthop;
struct interface *ifp;
+ struct zebra_ns *zns;
nexthop = nhlfe->nexthop;
if (!nexthop) // unexpected
* which will not be in the default
* VRF. So let's look in all of them
*/
- ifp = if_lookup_by_index(nexthop->ifindex, VRF_UNKNOWN);
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ ifp = if_lookup_by_index_per_ns(zns, nexthop->ifindex);
if (ifp && if_is_operative(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else
switch (nexthop->type) {
case NEXTHOP_TYPE_IFINDEX: {
+ struct zebra_ns *zns;
struct interface *ifp;
- ifp = if_lookup_by_index(
- nexthop->ifindex, VRF_UNKNOWN);
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ ifp = if_lookup_by_index_per_ns(
+ zns,
+ nexthop->ifindex);
vty_out(vty, "%15s", ifp->name);
break;
}
ns_id = zebra_ns_id_get(netnspath);
if (zserv_privs.change(ZPRIVS_LOWER))
zlog_err("Can't lower privileges");
+ if (ns_id == NS_UNKNOWN)
+ return;
ns_id_external = ns_map_nsid_with_external(ns_id, true);
/* if VRF with NS ID already present */
vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external);
return 0;
}
-int zebra_check_addr(struct prefix *p)
+int zebra_check_addr(const struct prefix *p)
{
if (p->family == AF_INET) {
uint32_t addr;
return nexthop;
}
-static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop,
+static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
struct nexthop *nexthop)
{
struct nexthop *resolved_hop;
route_map_result_t ret = RMAP_MATCH;
int family;
char buf[SRCDEST2STR_BUFFER];
- struct prefix *p, *src_p;
+ const struct prefix *p, *src_p;
srcdest_rnode_prefixes(rn, &p, &src_p);
if (rn->p.family == AF_INET)
return 1;
}
-void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
+void kernel_route_rib_pass_fail(struct route_node *rn, const struct prefix *p,
struct route_entry *re,
enum dp_results res)
{
{
struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
- struct prefix *p, *src_p;
+ const struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
srcdest_rnode_prefixes(rn, &p, &src_p);
{
struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
- struct prefix *p, *src_p;
+ const struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
srcdest_rnode_prefixes(rn, &p, &src_p);
}
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
- struct prefix *p, *src_p;
+ const struct prefix *p, *src_p;
+
srcdest_rnode_prefixes(rn, &p, &src_p);
redistribute_delete(p, src_p, re);
char buf[SRCDEST2STR_BUFFER];
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
- struct prefix *p, *src_p;
+ const struct prefix *p, *src_p;
+
srcdest_rnode_prefixes(rn, &p, &src_p);
vrf_id_t vrf_id = VRF_UNKNOWN;
}
route_map_result_t zebra_route_map_check(int family, int rib_type,
- uint8_t instance, struct prefix *p,
+ uint8_t instance,
+ const struct prefix *p,
struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag)
{
rmap = route_map_lookup_by_name(
proto_rm[family][ZEBRA_ROUTE_MAX]);
if (rmap) {
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, (struct prefix *)p,
+ RMAP_ZEBRA, &nh_obj);
}
return (ret);
const char *rmap_name);
extern route_map_result_t
zebra_route_map_check(int family, int rib_type, uint8_t instance,
- struct prefix *p, struct nexthop *nexthop,
+ const struct prefix *p, struct nexthop *nexthop,
vrf_id_t vrf_id, route_tag_t tag);
extern route_map_result_t
zebra_nht_route_map_check(int family, int client_proto, struct prefix *p,
#include "zebra/zebra_memory.h"
/* Install static route into rib. */
-void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
- struct prefix_ipv6 *src_p, struct static_route *si)
+void static_install_route(afi_t afi, safi_t safi, const struct prefix *p,
+ const struct prefix_ipv6 *src_p,
+ struct static_route *si)
{
struct route_entry *re;
struct route_node *rn;
}
/* Uninstall static route from RIB. */
-void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
- struct prefix_ipv6 *src_p, struct static_route *si)
+void static_uninstall_route(afi_t afi, safi_t safi, const struct prefix *p,
+ const struct prefix_ipv6 *src_p,
+ struct static_route *si)
{
struct route_node *rn;
struct route_entry *re;
struct route_table *stable;
struct route_node *rn;
struct static_route *si;
- struct prefix *p, *src_pp;
+ const struct prefix *p, *src_pp;
struct prefix_ipv6 *src_p;
struct vrf *vrf;
uint32_t table_id;
};
-extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
- struct prefix_ipv6 *src_p,
+extern void static_install_route(afi_t afi, safi_t safi, const struct prefix *p,
+ const struct prefix_ipv6 *src_p,
struct static_route *si);
-extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
- struct prefix_ipv6 *src_p,
+extern void static_uninstall_route(afi_t afi, safi_t safi,
+ const struct prefix *p,
+ const struct prefix_ipv6 *src_p,
struct static_route *si);
extern int static_add_route(afi_t, safi_t safi, uint8_t type, struct prefix *p,
zvrf->import_check_table[afi] = table;
}
- static_fixup_vrf_ids(zvrf);
-
- /*
- * We may have static routes that are now possible to
- * insert into the appropriate tables
- */
- static_config_install_delayed_routes(zvrf);
-
/* Kick off any VxLAN-EVPN processing. */
zebra_vxlan_vrf_enable(zvrf);
* Client thread events.
*
* These are used almost exclusively by client threads to drive their own event
- * loops. The only exception is in zebra_client_create(), which pushes an
+ * loops. The only exception is in zserv_client_create(), which pushes an
* initial ZSERV_CLIENT_READ event to start the API handler loop.
*/
enum zserv_client_event {
{
struct zserv *client = THREAD_ARG(thread);
- /*
- * Ensure these have been nulled. This does not equate to the
- * associated task(s) being scheduled or unscheduled on the client
- * pthread's threadmaster.
- */
- assert(!client->t_read);
- assert(!client->t_write);
-
/* synchronously stop thread */
frr_pthread_stop(client->pthread, NULL);
struct zserv *client = NULL;
struct thread t;
- zebra_client_create(-1);
+ zserv_client_create(-1);
frr_pthread_stop(client->pthread, NULL);
frr_pthread_destroy(client->pthread);