*new = *orig;
}
-void bgp_attr_deep_dup(struct attr *new, struct attr *orig)
-{
- if (orig->aspath)
- new->aspath = aspath_dup(orig->aspath);
-
- if (orig->community)
- new->community = community_dup(orig->community);
-
- if (orig->ecommunity)
- new->ecommunity = ecommunity_dup(orig->ecommunity);
- if (orig->cluster)
- new->cluster = cluster_dup(orig->cluster);
- if (orig->transit)
- new->transit = transit_dup(orig->transit);
- if (orig->encap_subtlvs)
- new->encap_subtlvs = encap_tlv_dup(orig->encap_subtlvs);
-#if ENABLE_BGP_VNC
- if (orig->vnc_subtlvs)
- new->vnc_subtlvs = encap_tlv_dup(orig->vnc_subtlvs);
-#endif
-}
-
-void bgp_attr_deep_free(struct attr *attr)
-{
- if (attr->aspath)
- aspath_free(attr->aspath);
-
- if (attr->community)
- community_free(attr->community);
-
- if (attr->ecommunity)
- ecommunity_free(&attr->ecommunity);
- if (attr->cluster)
- cluster_free(attr->cluster);
- if (attr->transit)
- transit_free(attr->transit);
- if (attr->encap_subtlvs)
- encap_free(attr->encap_subtlvs);
-#if ENABLE_BGP_VNC
- if (attr->vnc_subtlvs)
- encap_free(attr->vnc_subtlvs);
-#endif
-}
-
unsigned long int attr_count(void)
{
return attrhash->count;
/* 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)
{
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 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;
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)) {
+ *mpinfo_cp = *mpinfo;
+
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