/* All information about zebra. */
struct zclient *zclient = NULL;
-/* These array buffers are used in making a copy of the attributes for
- route-map apply. Arrays are being used here to minimize mallocs and
- frees for the temporary copy of the attributes.
- Given the zapi api expects the nexthop buffer to contain pointer to
- pointers for nexthops, we couldnt have used a single nexthop variable
- on the stack, hence we had two options:
- 1. maintain a linked-list and free it after zapi_*_route call
- 2. use an array to avoid number of mallocs.
- Number of supported next-hops are finite, use of arrays should be ok. */
-struct attr attr_cp[MULTIPATH_NUM];
-unsigned int attr_index = 0;
-
-/* Once per address-family initialization of the attribute array */
-#define BGP_INFO_ATTR_BUF_INIT() \
- do { \
- memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr)); \
- attr_index = 0; \
- } while (0)
-
-#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst) \
- do { \
- *info_dst = *info_src; \
- assert(attr_index != multipath_num); \
- bgp_attr_dup(&attr_cp[attr_index], info_src->attr); \
- bgp_attr_deep_dup(&attr_cp[attr_index], info_src->attr); \
- info_dst->attr = &attr_cp[attr_index]; \
- attr_index++; \
- } while (0)
-
-#define BGP_INFO_ATTR_BUF_FREE(info) \
- do { \
- bgp_attr_deep_free(info->attr); \
- } while (0)
-
-
/* Can we install into zebra? */
static inline int bgp_install_info_to_zebra(struct bgp *bgp)
{
struct interface *ifp;
struct bgp *bgp;
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp)
+ return 0;
+
s = zclient->ibuf;
ifp = zebra_interface_state_read(s, vrf_id);
if (!ifp) /* This may happen if we've just unregistered for a VRF. */
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name);
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp)
- return 0;
-
bgp_update_interface_nbrs(bgp, ifp, NULL);
- ifp->ifindex = IFINDEX_DELETED;
+ if_set_index(ifp, IFINDEX_INTERNAL);
return 0;
}
struct listnode *node, *nnode;
struct bgp *bgp;
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp)
+ return 0;
+
s = zclient->ibuf;
ifp = zebra_interface_state_read(s, vrf_id);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name);
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp)
- return 0;
-
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
bgp_connected_add(bgp, c);
struct listnode *node, *nnode;
struct bgp *bgp;
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp)
+ return 0;
+
s = zclient->ibuf;
ifp = zebra_interface_state_read(s, vrf_id);
if (!ifp)
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name);
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp)
- return 0;
-
for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c))
bgp_connected_delete(bgp, c);
zebra_size_t length, vrf_id_t vrf_id)
{
struct connected *ifc;
+ struct bgp *bgp;
+
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp)
+ return 0;
ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
}
if (if_is_operative(ifc->ifp)) {
- struct bgp *bgp;
-
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (!bgp)
- return 0;
-
bgp_connected_add(bgp, ifc);
+
/* If we have learnt of any neighbors on this interface,
* check to kick off any BGP interface-based neighbors,
* but only if this is a link-local address.
struct connected *ifc;
struct bgp *bgp;
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp)
+ return 0;
+
ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
if (ifc == NULL)
}
if (if_is_operative(ifc->ifp)) {
- bgp = bgp_lookup_by_vrf_id(vrf_id);
- if (bgp)
- bgp_connected_delete(bgp, ifc);
+ bgp_connected_delete(bgp, ifc);
}
connected_free(ifc);
static int zebra_read_route(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
+ enum nexthop_types_t nhtype;
struct zapi_route api;
union g_addr nexthop;
- unsigned int ifindex;
+ ifindex_t ifindex;
int add, i;
struct bgp *bgp;
nexthop = api.nexthops[0].gate;
ifindex = api.nexthops[0].ifindex;
+ nhtype = api.nexthops[0].type;
add = (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
if (add) {
/* Now perform the add/update. */
bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex,
- api.metric, api.type, api.instance,
- api.tag);
+ nhtype, api.metric, api.type,
+ api.instance, api.tag);
} else {
bgp_redistribute_delete(bgp, &api.prefix, api.type,
api.instance);
struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id)
{
- struct listnode *ifnode;
+ struct vrf *vrf;
struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv4 p;
struct prefix *cp;
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
p.family = AF_INET;
p.prefix = *addr;
p.prefixlen = IPV4_MAX_BITLEN;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
+ FOR_ALL_INTERFACES (vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
cp = connected->address;
struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id)
{
- struct listnode *ifnode;
+ struct vrf *vrf;
struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
cp = connected->address;
struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex,
vrf_id_t vrf_id)
{
- struct listnode *ifnode;
+ struct vrf *vrf;
struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix_ipv6 p;
struct prefix *cp;
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
p.family = AF_INET6;
p.prefix = *addr;
p.prefixlen = IPV6_MAX_BITLEN;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
+ FOR_ALL_INTERFACES (vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
cp = connected->address;
struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr,
ifindex_t ifindex, vrf_id_t vrf_id)
{
- struct listnode *ifnode;
+ struct vrf *vrf;
struct listnode *cnode;
struct interface *ifp;
struct connected *connected;
struct prefix *cp;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) {
+ vrf = vrf_lookup_by_id(vrf_id);
+ if (!vrf)
+ return NULL;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
cp = connected->address;
static int bgp_table_map_apply(struct route_map *map, struct prefix *p,
struct bgp_info *info)
{
- if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH)
+ route_map_result_t ret;
+
+ ret = route_map_apply(map, p, RMAP_BGP, info);
+ bgp_attr_flush(info->attr);
+
+ if (ret != RMAP_DENYMATCH)
return 1;
if (bgp_debug_zebra(p)) {
struct zapi_route api;
struct zapi_nexthop *api_nh;
int nh_family;
- int valid_nh_count = 0;
+ unsigned int valid_nh_count = 0;
int has_valid_label = 0;
u_char distance;
struct peer *peer;
struct bgp_info *mpinfo;
u_int32_t metric;
+ struct attr local_attr;
struct bgp_info local_info;
- struct bgp_info *info_cp = &local_info;
+ struct bgp_info *mpinfo_cp = &local_info;
route_tag_t tag;
mpls_label_t label;
* in
* the RIB */
if (info->sub_type == BGP_ROUTE_AGGREGATE)
- SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE);
+ zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
|| info->sub_type == BGP_ROUTE_AGGREGATE) {
SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL);
- /* Get nexthop address-family */
- if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))
- nh_family = AF_INET;
- else if (p->family == AF_INET6
- || (p->family == AF_INET
- && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
- nh_family = AF_INET6;
- else
- return;
-
- if (bgp->table_map[afi][safi].name)
- BGP_INFO_ATTR_BUF_INIT();
-
/* Metric is currently based on the best-path only */
metric = info->attr->med;
for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) {
+ if (valid_nh_count >= multipath_num)
+ break;
+
+ *mpinfo_cp = *mpinfo;
+
+ /* Get nexthop address-family */
+ if (p->family == AF_INET
+ && !BGP_ATTR_NEXTHOP_AFI_IP6(mpinfo_cp->attr))
+ nh_family = AF_INET;
+ else if (p->family == AF_INET6
+ || (p->family == AF_INET
+ && BGP_ATTR_NEXTHOP_AFI_IP6(mpinfo_cp->attr)))
+ nh_family = AF_INET6;
+ else
+ continue;
+
if (nh_family == AF_INET) {
struct in_addr *nexthop;
- nexthop = NULL;
-
if (bgp->table_map[afi][safi].name) {
/* Copy info and attributes, so the route-map
- apply doesn't modify the
- BGP route info. */
- BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
- if (bgp_table_map_apply(
+ apply doesn't modify the BGP route info. */
+ local_attr = *mpinfo->attr;
+ mpinfo_cp->attr = &local_attr;
+
+ if (!bgp_table_map_apply(
bgp->table_map[afi][safi].map, p,
- info_cp)) {
- if (mpinfo == info) {
- metric = info_cp->attr->med;
- tag = info_cp->attr->tag;
- }
- nexthop = &info_cp->attr->nexthop;
+ mpinfo_cp))
+ continue;
+
+ /* metric/tag is only allowed to be
+ * overridden on 1st nexthop */
+ if (mpinfo == info) {
+ metric = mpinfo_cp->attr->med;
+ tag = mpinfo_cp->attr->tag;
}
- BGP_INFO_ATTR_BUF_FREE(info_cp);
- } else
- nexthop = &mpinfo->attr->nexthop;
+ }
- if (nexthop == NULL)
- continue;
+ nexthop = &mpinfo_cp->attr->nexthop;
api_nh = &api.nexthops[valid_nh_count];
api_nh->gate.ipv4 = *nexthop;
struct in6_addr *nexthop;
ifindex = 0;
- nexthop = NULL;
if (bgp->table_map[afi][safi].name) {
/* Copy info and attributes, so the route-map
- apply doesn't modify the
- BGP route info. */
- BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
- if (bgp_table_map_apply(
+ apply doesn't modify the BGP route info. */
+ local_attr = *mpinfo->attr;
+ mpinfo_cp->attr = &local_attr;
+
+ if (!bgp_table_map_apply(
bgp->table_map[afi][safi].map, p,
- info_cp)) {
- if (mpinfo == info) {
- metric = info_cp->attr->med;
- tag = info_cp->attr->tag;
- }
- nexthop = bgp_info_to_ipv6_nexthop(
- info_cp);
+ mpinfo_cp))
+ continue;
+
+ /* metric/tag is only allowed to be
+ * overridden on 1st nexthop */
+ if (mpinfo == info) {
+ metric = mpinfo_cp->attr->med;
+ tag = mpinfo_cp->attr->tag;
}
- BGP_INFO_ATTR_BUF_FREE(info_cp);
- } else
- nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
-
- if (nexthop == NULL)
- continue;
+ }
+ nexthop = bgp_info_to_ipv6_nexthop(mpinfo_cp);
if ((mpinfo == info)
&& mpinfo->attr->mp_nexthop_len
->ifindex;
if (!ifindex) {
- if (mpinfo->peer->conf_if
- || mpinfo->peer->ifname)
+ if (mpinfo->peer->conf_if)
+ ifindex = mpinfo->peer->ifp->ifindex;
+ else if (mpinfo->peer->ifname)
ifindex = ifname2ifindex(
- mpinfo->peer->conf_if
- ? mpinfo->peer->conf_if
- : mpinfo->peer->ifname,
+ mpinfo->peer->ifname,
bgp->vrf_id);
else if (mpinfo->peer->nexthop.ifp)
ifindex = mpinfo->peer->nexthop.ifp
if (has_valid_label)
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
- if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE))
+ if (info->sub_type != BGP_ROUTE_AGGREGATE)
api.nexthop_num = valid_nh_count;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
for (i = 0; i < api.nexthop_num; i++) {
api_nh = &api.nexthops[i];
+ if (api_nh->type == NEXTHOP_TYPE_IPV4)
+ nh_family = AF_INET;
+ else
+ nh_family = AF_INET6;
inet_ntop(nh_family, &api_nh->gate, nh_buf,
sizeof(nh_buf));
if (red) {
listnode_delete(bgp->redist[afi][type], red);
XFREE(MTYPE_BGP_REDIST, red);
- if (!bgp->redist[afi][type]->count) {
- list_free(bgp->redist[afi][type]);
- bgp->redist[afi][type] = NULL;
- }
+ if (!bgp->redist[afi][type]->count)
+ list_delete_and_null(&bgp->redist[afi][type]);
}
}
vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
}
- /* Don't try to register if we're not connected to Zebra or Zebra
- * doesn't
- * know of this instance.
+ /*
+ * Don't try to register if we're not connected to Zebra or Zebra
+ * doesn't know of this instance.
+ *
+ * When we come up later well resend if needed.
*/
if (!bgp_install_info_to_zebra(bgp))
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_SUCCESS;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Tx redistribute add VRF %u afi %d %s %d",
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
}
+extern struct zebra_privs_t bgpd_privs;
+
void bgp_zebra_init(struct thread_master *master)
{
zclient_num_connects = 0;
/* Set default values. */
- zclient = zclient_new(master);
- zclient_init(zclient, ZEBRA_ROUTE_BGP, 0);
+ zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->router_id_update = bgp_router_id_update;
zclient->interface_add = bgp_interface_add;