mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +00:00
set community delete stops as soon as it hits a community-list entry with a deny
This commit is contained in:
parent
0a56c84405
commit
5cbea2885d
168
bgpd/bgp_clist.c
168
bgpd/bgp_clist.c
@ -331,6 +331,94 @@ community_list_entry_lookup (struct community_list *list, const void *arg,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
community_str_get (struct community *com, int i)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
u_int32_t comval;
|
||||||
|
u_int16_t as;
|
||||||
|
u_int16_t val;
|
||||||
|
char *str;
|
||||||
|
char *pnt;
|
||||||
|
|
||||||
|
memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
|
||||||
|
comval = ntohl (comval);
|
||||||
|
|
||||||
|
switch (comval)
|
||||||
|
{
|
||||||
|
case COMMUNITY_INTERNET:
|
||||||
|
len = strlen (" internet");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_NO_EXPORT:
|
||||||
|
len = strlen (" no-export");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_NO_ADVERTISE:
|
||||||
|
len = strlen (" no-advertise");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_LOCAL_AS:
|
||||||
|
len = strlen (" local-AS");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
len = strlen (" 65536:65535");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate memory. */
|
||||||
|
str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len);
|
||||||
|
|
||||||
|
switch (comval)
|
||||||
|
{
|
||||||
|
case COMMUNITY_INTERNET:
|
||||||
|
strcpy (pnt, "internet");
|
||||||
|
pnt += strlen ("internet");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_NO_EXPORT:
|
||||||
|
strcpy (pnt, "no-export");
|
||||||
|
pnt += strlen ("no-export");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_NO_ADVERTISE:
|
||||||
|
strcpy (pnt, "no-advertise");
|
||||||
|
pnt += strlen ("no-advertise");
|
||||||
|
break;
|
||||||
|
case COMMUNITY_LOCAL_AS:
|
||||||
|
strcpy (pnt, "local-AS");
|
||||||
|
pnt += strlen ("local-AS");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
as = (comval >> 16) & 0xFFFF;
|
||||||
|
val = comval & 0xFFFF;
|
||||||
|
sprintf (pnt, "%u:%d", as, val);
|
||||||
|
pnt += strlen (pnt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pnt = '\0';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal function to perform regular expression match for
|
||||||
|
* * a single community. */
|
||||||
|
static int
|
||||||
|
community_regexp_include (regex_t * reg, struct community *com, int i)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
/* When there is no communities attribute it is treated as empty
|
||||||
|
* string. */
|
||||||
|
if (com == NULL || com->size == 0)
|
||||||
|
str = "";
|
||||||
|
else
|
||||||
|
str = community_str_get (com, i);
|
||||||
|
|
||||||
|
/* Regular expression match. */
|
||||||
|
if (regexec (reg, str, 0, NULL, 0) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* No match. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Internal function to perform regular expression match for community
|
/* Internal function to perform regular expression match for community
|
||||||
attribute. */
|
attribute. */
|
||||||
static int
|
static int
|
||||||
@ -510,41 +598,63 @@ community_list_match_delete (struct community *com,
|
|||||||
struct community_list *list)
|
struct community_list *list)
|
||||||
{
|
{
|
||||||
struct community_entry *entry;
|
struct community_entry *entry;
|
||||||
|
u_int32_t val;
|
||||||
|
u_int32_t com_index_to_delete[com->size];
|
||||||
|
int delete_index = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
for (entry = list->head; entry; entry = entry->next)
|
/* Loop over each community value and evaluate each against the
|
||||||
|
* community-list. If we need to delete a community value add its index to
|
||||||
|
* com_index_to_delete.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < com->size; i++)
|
||||||
{
|
{
|
||||||
if (entry->any)
|
val = community_val_get (com, i);
|
||||||
{
|
|
||||||
if (entry->direct == COMMUNITY_PERMIT)
|
|
||||||
{
|
|
||||||
/* This is a tricky part. Currently only
|
|
||||||
* route_set_community_delete() uses this function. In the
|
|
||||||
* function com->size is zero, it free the community
|
|
||||||
* structure.
|
|
||||||
*/
|
|
||||||
com->size = 0;
|
|
||||||
}
|
|
||||||
return com;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((entry->style == COMMUNITY_LIST_STANDARD)
|
for (entry = list->head; entry; entry = entry->next)
|
||||||
&& (community_include (entry->u.com, COMMUNITY_INTERNET)
|
|
||||||
|| community_match (com, entry->u.com) ))
|
|
||||||
{
|
{
|
||||||
|
if (entry->any)
|
||||||
|
{
|
||||||
if (entry->direct == COMMUNITY_PERMIT)
|
if (entry->direct == COMMUNITY_PERMIT)
|
||||||
community_delete (com, entry->u.com);
|
{
|
||||||
else
|
com_index_to_delete[delete_index] = i;
|
||||||
break;
|
delete_index++;
|
||||||
}
|
}
|
||||||
else if ((entry->style == COMMUNITY_LIST_EXPANDED)
|
break;
|
||||||
&& community_regexp_match (com, entry->reg))
|
}
|
||||||
{
|
|
||||||
if (entry->direct == COMMUNITY_PERMIT)
|
else if ((entry->style == COMMUNITY_LIST_STANDARD)
|
||||||
community_regexp_delete (com, entry->reg);
|
&& (community_include (entry->u.com, COMMUNITY_INTERNET)
|
||||||
else
|
|| community_include (entry->u.com, val) ))
|
||||||
break;
|
{
|
||||||
}
|
if (entry->direct == COMMUNITY_PERMIT)
|
||||||
|
{
|
||||||
|
com_index_to_delete[delete_index] = i;
|
||||||
|
delete_index++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ((entry->style == COMMUNITY_LIST_EXPANDED)
|
||||||
|
&& community_regexp_include (entry->reg, com, i))
|
||||||
|
{
|
||||||
|
if (entry->direct == COMMUNITY_PERMIT)
|
||||||
|
{
|
||||||
|
com_index_to_delete[delete_index] = i;
|
||||||
|
delete_index++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete all of the communities we flagged for deletion */
|
||||||
|
for (i = delete_index-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
val = community_val_get (com, com_index_to_delete[i]);
|
||||||
|
community_del_val (com, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return com;
|
return com;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ community_include (struct community *com, u_int32_t val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_int32_t
|
u_int32_t
|
||||||
community_val_get (struct community *com, int i)
|
community_val_get (struct community *com, int i)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p;
|
||||||
|
@ -70,5 +70,6 @@ extern int community_include (struct community *, u_int32_t);
|
|||||||
extern void community_del_val (struct community *, u_int32_t *);
|
extern void community_del_val (struct community *, u_int32_t *);
|
||||||
extern unsigned long community_count (void);
|
extern unsigned long community_count (void);
|
||||||
extern struct hash *community_hash (void);
|
extern struct hash *community_hash (void);
|
||||||
|
extern u_int32_t community_val_get (struct community *com, int i);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_COMMUNITY_H */
|
#endif /* _QUAGGA_BGP_COMMUNITY_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user