bgpd: Convert ipv6_ecommunity to use accessor functions

Convert the `struct attr`->ipv6_ecommunity to use
accessor functions. We'll be able to reduce memory
usage in the `struct bgp_attr` by doing this.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2020-11-02 11:12:39 -05:00
parent 2a3f51cf6b
commit d04ac434f0
4 changed files with 49 additions and 22 deletions

View File

@ -663,8 +663,8 @@ unsigned int attrhash_key_make(const void *p)
MIX(lcommunity_hash_make(attr->lcommunity)); MIX(lcommunity_hash_make(attr->lcommunity));
if (attr->ecommunity) if (attr->ecommunity)
MIX(ecommunity_hash_make(attr->ecommunity)); MIX(ecommunity_hash_make(attr->ecommunity));
if (attr->ipv6_ecommunity) if (bgp_attr_get_ipv6_ecommunity(attr))
MIX(ecommunity_hash_make(attr->ipv6_ecommunity)); MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr)));
if (attr->cluster) if (attr->cluster)
MIX(cluster_hash_key_make(attr->cluster)); MIX(cluster_hash_key_make(attr->cluster));
if (attr->transit) if (attr->transit)
@ -703,7 +703,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
&& attr1->label_index == attr2->label_index && attr1->label_index == attr2->label_index
&& attr1->mp_nexthop_len == attr2->mp_nexthop_len && attr1->mp_nexthop_len == attr2->mp_nexthop_len
&& attr1->ecommunity == attr2->ecommunity && attr1->ecommunity == attr2->ecommunity
&& attr1->ipv6_ecommunity == attr2->ipv6_ecommunity && bgp_attr_get_ipv6_ecommunity(attr1)
== bgp_attr_get_ipv6_ecommunity(attr2)
&& attr1->lcommunity == attr2->lcommunity && attr1->lcommunity == attr2->lcommunity
&& attr1->cluster == attr2->cluster && attr1->cluster == attr2->cluster
&& attr1->transit == attr2->transit && attr1->transit == attr2->transit
@ -814,6 +815,7 @@ static void *bgp_attr_hash_alloc(void *p)
struct attr *bgp_attr_intern(struct attr *attr) struct attr *bgp_attr_intern(struct attr *attr)
{ {
struct attr *find; struct attr *find;
struct ecommunity *ecomm;
/* Intern referenced strucutre. */ /* Intern referenced strucutre. */
if (attr->aspath) { if (attr->aspath) {
@ -836,12 +838,13 @@ struct attr *bgp_attr_intern(struct attr *attr)
attr->ecommunity->refcnt++; attr->ecommunity->refcnt++;
} }
if (attr->ipv6_ecommunity) { ecomm = bgp_attr_get_ipv6_ecommunity(attr);
if (!attr->ipv6_ecommunity->refcnt) if (ecomm) {
attr->ipv6_ecommunity = if (!ecomm->refcnt)
ecommunity_intern(attr->ipv6_ecommunity); bgp_attr_set_ipv6_ecommunity(attr,
ecommunity_intern(ecomm));
else else
attr->ipv6_ecommunity->refcnt++; ecomm->refcnt++;
} }
if (attr->lcommunity) { if (attr->lcommunity) {
@ -1036,6 +1039,8 @@ struct attr *bgp_attr_aggregate_intern(
/* Unintern just the sub-components of the attr, but not the attr */ /* Unintern just the sub-components of the attr, but not the attr */
void bgp_attr_unintern_sub(struct attr *attr) void bgp_attr_unintern_sub(struct attr *attr)
{ {
struct ecommunity *ecomm;
/* aspath refcount shoud be decrement. */ /* aspath refcount shoud be decrement. */
if (attr->aspath) if (attr->aspath)
aspath_unintern(&attr->aspath); aspath_unintern(&attr->aspath);
@ -1048,8 +1053,10 @@ void bgp_attr_unintern_sub(struct attr *attr)
ecommunity_unintern(&attr->ecommunity); ecommunity_unintern(&attr->ecommunity);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
ecommunity_unintern(&attr->ipv6_ecommunity); ecomm = bgp_attr_get_ipv6_ecommunity(attr);
ecommunity_unintern(&ecomm);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
bgp_attr_set_ipv6_ecommunity(attr, NULL);
if (attr->lcommunity) if (attr->lcommunity)
lcommunity_unintern(&attr->lcommunity); lcommunity_unintern(&attr->lcommunity);
@ -1127,6 +1134,8 @@ void bgp_attr_unintern(struct attr **pattr)
void bgp_attr_flush(struct attr *attr) void bgp_attr_flush(struct attr *attr)
{ {
struct ecommunity *ecomm;
if (attr->aspath && !attr->aspath->refcnt) { if (attr->aspath && !attr->aspath->refcnt) {
aspath_free(attr->aspath); aspath_free(attr->aspath);
attr->aspath = NULL; attr->aspath = NULL;
@ -1135,8 +1144,10 @@ void bgp_attr_flush(struct attr *attr)
community_free(&attr->community); community_free(&attr->community);
if (attr->ecommunity && !attr->ecommunity->refcnt) if (attr->ecommunity && !attr->ecommunity->refcnt)
ecommunity_free(&attr->ecommunity); ecommunity_free(&attr->ecommunity);
if (attr->ipv6_ecommunity && !attr->ecommunity->refcnt) ecomm = bgp_attr_get_ipv6_ecommunity(attr);
ecommunity_free(&attr->ipv6_ecommunity); if (ecomm && !ecomm->refcnt)
ecommunity_free(&ecomm);
bgp_attr_set_ipv6_ecommunity(attr, NULL);
if (attr->lcommunity && !attr->lcommunity->refcnt) if (attr->lcommunity && !attr->lcommunity->refcnt)
lcommunity_free(&attr->lcommunity); lcommunity_free(&attr->lcommunity);
if (attr->cluster && !attr->cluster->refcnt) { if (attr->cluster && !attr->cluster->refcnt) {
@ -2300,19 +2311,21 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
struct peer *const peer = args->peer; struct peer *const peer = args->peer;
struct attr *const attr = args->attr; struct attr *const attr = args->attr;
const bgp_size_t length = args->length; const bgp_size_t length = args->length;
struct ecommunity *ipv6_ecomm = NULL;
if (length == 0) { if (length == 0) {
attr->ipv6_ecommunity = NULL; bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total); args->total);
} }
attr->ipv6_ecommunity = ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
ecommunity_parse_ipv6(stream_pnt(peer->curr), length); bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
/* XXX: fix ecommunity_parse to use stream API */ /* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp(peer->curr, length); stream_forward_getp(peer->curr, length);
if (!attr->ipv6_ecommunity) if (!ipv6_ecomm)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total); args->total);

View File

@ -469,4 +469,16 @@ static inline void bgp_attr_set_pmsi_tnl_type(struct attr *attr,
attr->pmsi_tnl_type = pmsi_tnl_type; attr->pmsi_tnl_type = pmsi_tnl_type;
} }
static inline struct ecommunity *
bgp_attr_get_ipv6_ecommunity(const struct attr *attr)
{
return attr->ipv6_ecommunity;
}
static inline void bgp_attr_set_ipv6_ecommunity(struct attr *attr,
struct ecommunity *ipv6_ecomm)
{
attr->ipv6_ecommunity = ipv6_ecomm;
}
#endif /* _QUAGGA_BGP_ATTR_H */ #endif /* _QUAGGA_BGP_ATTR_H */

View File

@ -268,6 +268,7 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object *json_ecom_path = NULL; json_object *json_ecom_path = NULL;
json_object *json_time_path = NULL; json_object *json_time_path = NULL;
char timebuf[BGP_UPTIME_LEN]; char timebuf[BGP_UPTIME_LEN];
struct ecommunity *ipv6_ecomm;
if (p == NULL || p->family != AF_FLOWSPEC) if (p == NULL || p->family != AF_FLOWSPEC)
return; return;
@ -298,16 +299,17 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object_array_add(json_paths, json_nlri_path); json_object_array_add(json_paths, json_nlri_path);
if (!path) if (!path)
return; return;
if (path->attr &&
(path->attr->ecommunity || path->attr->ipv6_ecommunity)) { ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(path->attr);
if (path->attr && (path->attr->ecommunity || ipv6_ecomm)) {
/* Print attribute */ /* Print attribute */
attr = path->attr; attr = path->attr;
if (attr->ecommunity) if (attr->ecommunity)
s1 = ecommunity_ecom2str(attr->ecommunity, s1 = ecommunity_ecom2str(attr->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP, 0); ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
if (attr->ipv6_ecommunity) if (ipv6_ecomm)
s2 = ecommunity_ecom2str(attr->ipv6_ecommunity, s2 = ecommunity_ecom2str(
ECOMMUNITY_FORMAT_ROUTE_MAP, 0); ipv6_ecomm, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
if (!s1 && !s2) if (!s1 && !s2)
return; return;
if (display == NLRI_STRING_FORMAT_LARGE) if (display == NLRI_STRING_FORMAT_LARGE)

View File

@ -915,10 +915,10 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
api->action_num++; api->action_num++;
} }
} }
if (path && path->attr && path->attr->ipv6_ecommunity) { if (path && path->attr && bgp_attr_get_ipv6_ecommunity(path->attr)) {
struct ecommunity_val_ipv6 *ipv6_ecom_eval; struct ecommunity_val_ipv6 *ipv6_ecom_eval;
ecom = path->attr->ipv6_ecommunity; ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
for (i = 0; i < ecom->size; i++) { for (i = 0; i < ecom->size; i++) {
ipv6_ecom_eval = (struct ecommunity_val_ipv6 *) ipv6_ecom_eval = (struct ecommunity_val_ipv6 *)
(ecom->val + (i * ecom->unit_size)); (ecom->val + (i * ecom->unit_size));