/* Allocate a new ecommunities. */
struct ecommunity *ecommunity_new(void)
{
- return XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity));
+ struct ecommunity *ecom;
+
+ ecom = (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY,
+ sizeof(struct ecommunity));
+ ecom->unit_size = ECOMMUNITY_SIZE;
+ return ecom;
}
void ecommunity_strfree(char **s)
once and whether the new value should replace what is existing or
not.
*/
-bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval,
- bool unique, bool overwrite)
+static bool ecommunity_add_val_internal(struct ecommunity *ecom, const void *eval,
+ bool unique, bool overwrite, uint8_t ecom_size)
{
int c, ins_idx;
+ const struct ecommunity_val *eval4 = (struct ecommunity_val *)eval;
+ const struct ecommunity_val_ipv6 *eval6 = (struct ecommunity_val_ipv6 *)eval;
/* When this is fist value, just add it. */
if (ecom->val == NULL) {
ecom->size = 1;
- ecom->val = XCALLOC(MTYPE_ECOMMUNITY_VAL, ECOMMUNITY_SIZE);
- memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE);
+ ecom->val = XMALLOC(MTYPE_ECOMMUNITY_VAL,
+ ecom_length_size(ecom, ecom_size));
+ memcpy(ecom->val, eval, ecom_size);
return true;
}
/* If the value already exists in the structure return 0. */
/* check also if the extended community itself exists. */
c = 0;
+
ins_idx = -1;
for (uint8_t *p = ecom->val; c < ecom->size;
- p += ECOMMUNITY_SIZE, c++) {
+ p += ecom_size, c++) {
if (unique) {
- if (p[0] == eval->val[0] &&
- p[1] == eval->val[1]) {
- if (overwrite) {
- memcpy(p, eval->val, ECOMMUNITY_SIZE);
- return true;
+ if (ecom_size == ECOMMUNITY_SIZE) {
+ if (p[0] == eval4->val[0] &&
+ p[1] == eval4->val[1]) {
+ if (overwrite) {
+ memcpy(p, eval4->val, ecom_size);
+ return true;
+ }
+ return false;
+ }
+ } else {
+ if (p[0] == eval6->val[0] &&
+ p[1] == eval6->val[1]) {
+ if (overwrite) {
+ memcpy(p, eval6->val, ecom_size);
+ return true;
+ }
+ return false;
}
- return false;
}
}
- int ret = memcmp(p, eval->val, ECOMMUNITY_SIZE);
+ int ret = memcmp(p, eval, ecom_size);
if (ret == 0)
return false;
if (ret > 0) {
/* Add the value to the structure with numerical sorting. */
ecom->size++;
ecom->val = XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom->val,
- ecom->size * ECOMMUNITY_SIZE);
+ ecom_length_size(ecom, ecom_size));
+
- memmove(ecom->val + ((ins_idx + 1) * ECOMMUNITY_SIZE),
- ecom->val + (ins_idx * ECOMMUNITY_SIZE),
- (ecom->size - 1 - ins_idx) * ECOMMUNITY_SIZE);
- memcpy(ecom->val + (ins_idx * ECOMMUNITY_SIZE),
- eval->val, ECOMMUNITY_SIZE);
+ memmove(ecom->val + ((ins_idx + 1) * ecom_size),
+ ecom->val + (ins_idx * ecom_size),
+ (ecom->size - 1 - ins_idx) * ecom_size);
+ memcpy(ecom->val + (ins_idx * ecom_size),
+ eval, ecom_size);
return true;
}
-/* This function takes pointer to Extended Communites strucutre then
- create a new Extended Communities structure by uniq and sort each
- Extended Communities value. */
-struct ecommunity *ecommunity_uniq_sort(struct ecommunity *ecom)
+/* Add a new Extended Communities value to Extended Communities
+ Attribute structure. When the value is already exists in the
+ structure, we don't add the value. Newly added value is sorted by
+ numerical order. When the value is added to the structure return 1
+ else return 0. */
+bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval,
+ bool unique, bool overwrite)
+{
+ return ecommunity_add_val_internal(ecom, (const void *)eval, unique,
+ overwrite, ECOMMUNITY_SIZE);
+}
+
+bool ecommunity_add_val_ipv6(struct ecommunity *ecom, struct ecommunity_val_ipv6 *eval,
+ bool unique, bool overwrite)
+{
+ return ecommunity_add_val_internal(ecom, (const void *)eval, unique,
+ overwrite, IPV6_ECOMMUNITY_SIZE);
+}
+
+static struct ecommunity *
+ecommunity_uniq_sort_internal(struct ecommunity *ecom,
+ unsigned short ecom_size)
{
int i;
struct ecommunity *new;
- struct ecommunity_val *eval;
+ const void *eval;
if (!ecom)
return NULL;
new = ecommunity_new();
+ new->unit_size = ecom_size;
for (i = 0; i < ecom->size; i++) {
- eval = (struct ecommunity_val *)(ecom->val
- + (i * ECOMMUNITY_SIZE));
- ecommunity_add_val(new, eval, false, false);
+ eval = (void *)(ecom->val
+ + (i * ecom_size));
+ ecommunity_add_val_internal(new, eval, false, false, ecom_size);
}
return new;
}
+/* This function takes pointer to Extended Communites strucutre then
+ create a new Extended Communities structure by uniq and sort each
+ Extended Communities value. */
+struct ecommunity *ecommunity_uniq_sort(struct ecommunity *ecom)
+{
+ return ecommunity_uniq_sort_internal(ecom, ECOMMUNITY_SIZE);
+}
+
/* Parse Extended Communites Attribute in BGP packet. */
-struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length)
+static struct ecommunity *ecommunity_parse_internal(uint8_t *pnt,
+ unsigned short length,
+ unsigned short size_ecom)
{
struct ecommunity tmp;
struct ecommunity *new;
/* Length check. */
- if (length % ECOMMUNITY_SIZE)
+ if (length % size_ecom)
return NULL;
/* Prepare tmporary structure for making a new Extended Communities
Attribute. */
- tmp.size = length / ECOMMUNITY_SIZE;
+ tmp.size = length / size_ecom;
tmp.val = pnt;
/* Create a new Extended Communities Attribute by uniq and sort each
Extended Communities value */
- new = ecommunity_uniq_sort(&tmp);
+ new = ecommunity_uniq_sort_internal(&tmp, size_ecom);
return ecommunity_intern(new);
}
+struct ecommunity *ecommunity_parse(uint8_t *pnt,
+ unsigned short length)
+{
+ return ecommunity_parse_internal(pnt, length, ECOMMUNITY_SIZE);
+}
+
+struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
+ unsigned short length)
+{
+ return ecommunity_parse_internal(pnt, length,
+ IPV6_ECOMMUNITY_SIZE);
+}
+
/* Duplicate the Extended Communities Attribute structure. */
struct ecommunity *ecommunity_dup(struct ecommunity *ecom)
{
new = XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity));
new->size = ecom->size;
+ new->unit_size = ecom->unit_size;
if (new->size) {
new->val = XMALLOC(MTYPE_ECOMMUNITY_VAL,
- ecom->size * ECOMMUNITY_SIZE);
- memcpy(new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE);
+ ecom->size * ecom->unit_size);
+ memcpy(new->val, ecom->val, ecom->size * ecom->unit_size);
} else
new->val = NULL;
return new;
if (ecom1->val)
ecom1->val =
XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom1->val,
- (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
+ (ecom1->size + ecom2->size) *
+ ecom1->unit_size);
else
ecom1->val =
XMALLOC(MTYPE_ECOMMUNITY_VAL,
- (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
+ (ecom1->size + ecom2->size) *
+ ecom1->unit_size);
- memcpy(ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), ecom2->val,
- ecom2->size * ECOMMUNITY_SIZE);
+ memcpy(ecom1->val + (ecom1->size * ecom1->unit_size), ecom2->val,
+ ecom2->size * ecom1->unit_size);
ecom1->size += ecom2->size;
return ecom1;
struct ecommunity *find;
assert(ecom->refcnt == 0);
-
find = (struct ecommunity *)hash_get(ecomhash, ecom, hash_alloc_intern);
-
if (find != ecom)
ecommunity_free(&ecom);
unsigned int ecommunity_hash_make(const void *arg)
{
const struct ecommunity *ecom = arg;
- int size = ecom->size * ECOMMUNITY_SIZE;
+ int size = ecom->size * ecom->unit_size;
return jhash(ecom->val, size, 0x564321ab);
}
if (ecom1 == NULL || ecom2 == NULL)
return false;
+ if (ecom1->unit_size != ecom2->unit_size)
+ return false;
+
return (ecom1->size == ecom2->size
- && memcmp(ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE)
- == 0);
+ && memcmp(ecom1->val, ecom2->val, ecom1->size *
+ ecom1->unit_size) == 0);
}
/* Initialize Extended Comminities related hash. */
ecommunity_token_rt,
ecommunity_token_soo,
ecommunity_token_val,
+ ecommunity_token_rt6,
+ ecommunity_token_val6,
};
-/*
- * Encode BGP extended community from passed values. Supports types
- * defined in RFC 4360 and well-known sub-types.
- */
-static int ecommunity_encode(uint8_t type, uint8_t sub_type, int trans, as_t as,
- struct in_addr ip, uint32_t val,
- struct ecommunity_val *eval)
+static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type,
+ int trans, as_t as,
+ struct in_addr *ip,
+ struct in6_addr *ip6,
+ uint32_t val,
+ void *eval_ptr)
{
+ struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr;
+ struct ecommunity_val_ipv6 *eval6 =
+ (struct ecommunity_val_ipv6 *)eval_ptr;
+
assert(eval);
if (type == ECOMMUNITY_ENCODE_AS) {
if (as > BGP_AS_MAX)
|| type == ECOMMUNITY_ENCODE_AS4) {
if (val > UINT16_MAX)
return -1;
+ } else if (type == ECOMMUNITY_ENCODE_TRANS_EXP &&
+ sub_type == ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 &&
+ (!ip6 || val > UINT16_MAX)) {
+ return -1;
}
/* Fill in the values. */
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
} else if (type == ECOMMUNITY_ENCODE_IP) {
- memcpy(&eval->val[2], &ip, sizeof(struct in_addr));
+ memcpy(&eval->val[2], ip, sizeof(struct in_addr));
eval->val[6] = (val >> 8) & 0xff;
eval->val[7] = val & 0xff;
+ } else if (type == ECOMMUNITY_ENCODE_TRANS_EXP &&
+ sub_type == ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) {
+ memcpy(&eval6->val[2], ip6, sizeof(struct in6_addr));
+ eval6->val[18] = (val >> 8) & 0xff;
+ eval6->val[19] = val & 0xff;
} else {
eval->val[2] = (as >> 24) & 0xff;
eval->val[3] = (as >> 16) & 0xff;
return 0;
}
+/*
+ * Encode BGP extended community from passed values. Supports types
+ * defined in RFC 4360 and well-known sub-types.
+ */
+static int ecommunity_encode(uint8_t type, uint8_t sub_type, int trans, as_t as,
+ struct in_addr ip, uint32_t val,
+ struct ecommunity_val *eval)
+{
+ return ecommunity_encode_internal(type, sub_type, trans, as,
+ &ip, NULL, val, (void *)eval);
+}
+
/* Get next Extended Communities token from the string. */
static const char *ecommunity_gettoken(const char *str,
- struct ecommunity_val *eval,
+ void *eval_ptr,
enum ecommunity_token *token)
{
int ret;
const char *p = str;
char *endptr;
struct in_addr ip;
+ struct in6_addr ip6;
as_t as = 0;
uint32_t val = 0;
uint8_t ecomm_type;
char buf[INET_ADDRSTRLEN + 1];
-
+ struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr;
/* Skip white space. */
while (isspace((unsigned char)*p)) {
p++;
p++;
if (tolower((unsigned char)*p) == 't') {
p++;
- *token = ecommunity_token_rt;
+ if (*p != '\0' && tolower((int)*p) == '6')
+ *token = ecommunity_token_rt6;
+ else
+ *token = ecommunity_token_rt;
return p;
}
if (isspace((unsigned char)*p) || *p == '\0') {
* a) A.B.C.D:MN
* b) EF:OPQR
* c) GHJK:MN
+ * d) <IPV6>:MN (only with rt6)
*
* A.B.C.D: Four Byte IP
* EF: Two byte ASN
* OPQR: Four byte value
*
*/
+ /* IPv6 case : look for last ':' */
+ if (*token == ecommunity_token_rt6 ||
+ *token == ecommunity_token_val6) {
+ char *limit;
+
+ limit = endptr = strrchr(p, ':');
+ if (!endptr)
+ goto error;
+ endptr++;
+ as = strtoul(endptr, &endptr, 10);
+ if (*endptr != '\0' || as == BGP_AS4_MAX)
+ goto error;
+ memcpy(buf, p, (limit - p));
+ buf[limit - p] = '\0';
+ ret = inet_pton(AF_INET6, buf, &ip6);
+ if (ret == 0)
+ goto error;
+ ecomm_type = ECOMMUNITY_ENCODE_TRANS_EXP;
+ if (ecommunity_encode_internal(ecomm_type,
+ ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6,
+ 1, 0, NULL, &ip6, as, eval_ptr))
+ goto error;
+ *token = ecommunity_token_val6;
+ while (isdigit((int)*p) || *p == ':' || *p == '.') {
+ p++;
+ }
+ return p;
+ }
while (isdigit((unsigned char)*p) || *p == ':' || *p == '.') {
if (*p == ':') {
if (separator)
return p;
}
-/* Convert string to extended community attribute.
-
- When type is already known, please specify both str and type. str
- should not include keyword such as "rt" and "soo". Type is
- ECOMMUNITY_ROUTE_TARGET or ECOMMUNITY_SITE_ORIGIN.
- keyword_included should be zero.
-
- For example route-map's "set extcommunity" command case:
-
- "rt 100:1 100:2 100:3" -> str = "100:1 100:2 100:3"
- type = ECOMMUNITY_ROUTE_TARGET
- keyword_included = 0
-
- "soo 100:1" -> str = "100:1"
- type = ECOMMUNITY_SITE_ORIGIN
- keyword_included = 0
-
- When string includes keyword for each extended community value.
- Please specify keyword_included as non-zero value.
-
- For example standard extcommunity-list case:
-
- "rt 100:1 rt 100:2 soo 100:1" -> str = "rt 100:1 rt 100:2 soo 100:1"
- type = 0
- keyword_include = 1
-*/
-struct ecommunity *ecommunity_str2com(const char *str, int type,
- int keyword_included)
+static struct ecommunity *ecommunity_str2com_internal(const char *str, int type,
+ int keyword_included,
+ bool is_ipv6_extcomm)
{
struct ecommunity *ecom = NULL;
enum ecommunity_token token = ecommunity_token_unknown;
- struct ecommunity_val eval;
+ struct ecommunity_val_ipv6 eval;
int keyword = 0;
- while ((str = ecommunity_gettoken(str, &eval, &token))) {
+ if (is_ipv6_extcomm)
+ token = ecommunity_token_rt6;
+ while ((str = ecommunity_gettoken(str, (void *)&eval, &token))) {
switch (token) {
case ecommunity_token_rt:
case ecommunity_token_soo:
}
keyword = 1;
- if (token == ecommunity_token_rt) {
+ if (token == ecommunity_token_rt ||
+ token == ecommunity_token_rt6) {
type = ECOMMUNITY_ROUTE_TARGET;
}
if (token == ecommunity_token_soo) {
if (ecom == NULL)
ecom = ecommunity_new();
eval.val[1] = type;
- ecommunity_add_val(ecom, &eval, false, false);
+ ecommunity_add_val_internal(ecom, (void *)&eval, false, false,
+ ecom->unit_size);
+ break;
+ case ecommunity_token_val6:
+ if (keyword_included) {
+ if (!keyword) {
+ if (ecom)
+ ecommunity_free(&ecom);
+ return NULL;
+ }
+ keyword = 0;
+ }
+ if (ecom == NULL)
+ ecom = ecommunity_new();
+ ecom->unit_size = IPV6_ECOMMUNITY_SIZE;
+ eval.val[1] = type;
+ ecommunity_add_val_internal(ecom, (void *)&eval, false, false,
+ ecom->unit_size);
break;
case ecommunity_token_unknown:
default:
return ecom;
}
-static int ecommunity_rt_soo_str(char *buf, size_t bufsz, const uint8_t *pnt,
- int type, int sub_type, int format)
+/* Convert string to extended community attribute.
+
+ When type is already known, please specify both str and type. str
+ should not include keyword such as "rt" and "soo". Type is
+ ECOMMUNITY_ROUTE_TARGET or ECOMMUNITY_SITE_ORIGIN.
+ keyword_included should be zero.
+
+ For example route-map's "set extcommunity" command case:
+
+ "rt 100:1 100:2 100:3" -> str = "100:1 100:2 100:3"
+ type = ECOMMUNITY_ROUTE_TARGET
+ keyword_included = 0
+
+ "soo 100:1" -> str = "100:1"
+ type = ECOMMUNITY_SITE_ORIGIN
+ keyword_included = 0
+
+ When string includes keyword for each extended community value.
+ Please specify keyword_included as non-zero value.
+
+ For example standard extcommunity-list case:
+
+ "rt 100:1 rt 100:2 soo 100:1" -> str = "rt 100:1 rt 100:2 soo 100:1"
+ type = 0
+ keyword_include = 1
+*/
+struct ecommunity *ecommunity_str2com(const char *str, int type,
+ int keyword_included)
+{
+ return ecommunity_str2com_internal(str, type,
+ keyword_included, false);
+}
+
+struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
+ int keyword_included)
+{
+ return ecommunity_str2com_internal(str, type,
+ keyword_included, true);
+}
+
+static int ecommunity_rt_soo_str_internal(char *buf, size_t bufsz,
+ const uint8_t *pnt, int type,
+ int sub_type, int format,
+ unsigned short ecom_size)
{
int len = 0;
const char *prefix;
+ char buf_local[INET6_ADDRSTRLEN];
/* For parse Extended Community attribute tupple. */
struct ecommunity_as eas;
struct ecommunity_ip eip;
-
+ struct ecommunity_ip6 eip6;
/* Determine prefix for string, if any. */
switch (format) {
len = snprintf(buf, bufsz, "%s%u:%u", prefix, eas.as, eas.val);
} else if (type == ECOMMUNITY_ENCODE_AS) {
- eas.as = (*pnt++ << 8);
- eas.as |= (*pnt++);
- pnt = ptr_get_be32(pnt, &eas.val);
+ if (ecom_size == ECOMMUNITY_SIZE) {
+ eas.as = (*pnt++ << 8);
+ eas.as |= (*pnt++);
+ pnt = ptr_get_be32(pnt, &eas.val);
- len = snprintf(buf, bufsz, "%s%u:%u", prefix, eas.as, eas.val);
+ len = snprintf(buf, bufsz, "%s%u:%u", prefix, eas.as, eas.val);
+ } else {
+ /* this is an IPv6 ext community
+ */
+ memcpy(&eip6.ip, pnt, 16);
+ pnt += 16;
+ eip6.val = (*pnt++ << 8);
+ eip6.val |= (*pnt++);
+
+ inet_ntop(AF_INET6, &eip6.ip, buf_local, sizeof(buf_local));
+ len = snprintf(buf, bufsz, "%s%s:%u", prefix,
+ buf_local, eip6.val);
+ }
} else if (type == ECOMMUNITY_ENCODE_IP) {
memcpy(&eip.ip, pnt, 4);
pnt += 4;
return len;
}
+static int ecommunity_rt_soo_str(char *buf, size_t bufsz, const uint8_t *pnt,
+ int type, int sub_type, int format)
+{
+ return ecommunity_rt_soo_str_internal(buf, bufsz, pnt, type,
+ sub_type, format,
+ ECOMMUNITY_SIZE);
+}
+
static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)
{
int len = 0;
type == ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
type == ECOMMUNITY_EXTENDED_COMMUNITY_PART_3) {
sub_type = *pnt++;
- if (sub_type == ECOMMUNITY_REDIRECT_VRF) {
- char buf[16] = {};
- ecommunity_rt_soo_str(
- buf, sizeof(buf), pnt,
- type & ~ECOMMUNITY_ENCODE_TRANS_EXP,
- ECOMMUNITY_ROUTE_TARGET,
- ECOMMUNITY_FORMAT_DISPLAY);
+
+ if (sub_type == ECOMMUNITY_ROUTE_TARGET) {
+ char buf[64];
+
+ memset(buf, 0, sizeof(buf));
+ ecommunity_rt_soo_str_internal(buf, sizeof(buf),
+ (const uint8_t *)pnt,
+ type &
+ ~ECOMMUNITY_ENCODE_TRANS_EXP,
+ ECOMMUNITY_ROUTE_TARGET,
+ format,
+ ecom->unit_size);
+ snprintf(encbuf, sizeof(encbuf), "%s", buf);
+ } else if (sub_type == ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6) {
+ char buf[64];
+
+ memset(buf, 0, sizeof(buf));
+ ecommunity_rt_soo_str_internal(buf, sizeof(buf),
+ (const uint8_t *)pnt,
+ type &
+ ~ECOMMUNITY_ENCODE_TRANS_EXP,
+ ECOMMUNITY_ROUTE_TARGET,
+ ECOMMUNITY_FORMAT_DISPLAY,
+ ecom->unit_size);
+ snprintf(encbuf, sizeof(encbuf), "FS:redirect VRF %s", buf);
+ } else if (sub_type == ECOMMUNITY_REDIRECT_VRF) {
+ char buf[16];
+
+ memset(buf, 0, sizeof(buf));
+ ecommunity_rt_soo_str(buf, sizeof(buf), (const uint8_t *)pnt,
+ type &
+ ~ECOMMUNITY_ENCODE_TRANS_EXP,
+ ECOMMUNITY_ROUTE_TARGET,
+ ECOMMUNITY_FORMAT_DISPLAY);
snprintf(encbuf, sizeof(encbuf),
"FS:redirect VRF %s", buf);
+ snprintf(encbuf, sizeof(encbuf), "FS:redirect VRF %s", buf);
} else if (type != ECOMMUNITY_ENCODE_TRANS_EXP)
unk_ecom = 1;
else if (sub_type == ECOMMUNITY_TRAFFIC_ACTION) {
/* Every community on com2 needs to be on com1 for this to match */
while (i < ecom1->size && j < ecom2->size) {
- if (memcmp(ecom1->val + i * ECOMMUNITY_SIZE,
- ecom2->val + j * ECOMMUNITY_SIZE, ECOMMUNITY_SIZE)
+ if (memcmp(ecom1->val + i * ecom1->unit_size,
+ ecom2->val + j * ecom2->unit_size,
+ ecom2->unit_size)
== 0)
j++;
i++;
/* If the value already exists in the structure return 0. */
c = 0;
- for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
+ for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++) {
if (p == NULL) {
continue;
}
* multiple times, handle that.
*/
c = 0;
- for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
+ for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++) {
if (p[0] == type && p[1] == subtype)
found++;
}
/* Strip matching ext community(ies). */
new = XMALLOC(MTYPE_ECOMMUNITY_VAL,
- (ecom->size - found) * ECOMMUNITY_SIZE);
+ (ecom->size - found) * ecom->unit_size);
q = new;
- for (c = 0, p = ecom->val; c < ecom->size; c++, p += ECOMMUNITY_SIZE) {
+ for (c = 0, p = ecom->val; c < ecom->size; c++, p += ecom->unit_size) {
if (!(p[0] == type && p[1] == subtype)) {
- memcpy(q, p, ECOMMUNITY_SIZE);
- q += ECOMMUNITY_SIZE;
+ memcpy(q, p, ecom->unit_size);
+ q += ecom->unit_size;
}
}
XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
if (ecom == NULL || ecom->val == NULL)
return false;
c = 0;
- for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) {
- if (!memcmp(p, eval->val, ECOMMUNITY_SIZE)) {
+ for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++) {
+ if (!memcmp(p, eval->val, ecom->unit_size)) {
found = 1;
break;
}
/* Delete the selected value */
ecom->size--;
- p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE);
+ p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size);
if (c != 0)
- memcpy(p, ecom->val, c * ECOMMUNITY_SIZE);
+ memcpy(p, ecom->val, c * ecom->unit_size);
if ((ecom->size - c) != 0)
- memcpy(p + (c)*ECOMMUNITY_SIZE,
- ecom->val + (c + 1) * ECOMMUNITY_SIZE,
- (ecom->size - c) * ECOMMUNITY_SIZE);
+ memcpy(p + (c)*ecom->unit_size,
+ ecom->val + (c + 1) * ecom->unit_size,
+ (ecom->size - c) * ecom->unit_size);
XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
ecom->val = p;
return true;