Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib, bgpd, tests, zebra: prefix_sg changes for V6 VTEP #15900

Merged
merged 7 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bgpd/bgp_evpn_mh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2455,7 +2455,7 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty,
}

static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
uint8_t vtep_str_size)
size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
Expand Down Expand Up @@ -3956,7 +3956,7 @@ void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn)

static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
struct bgp_evpn_es_evi *es_evi,
uint8_t vtep_str_size)
size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
Expand Down
13 changes: 11 additions & 2 deletions lib/ipaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ struct ipaddr {
#define IS_IPADDR_V4(p) ((p)->ipa_type == IPADDR_V4)
#define IS_IPADDR_V6(p) ((p)->ipa_type == IPADDR_V6)

#define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4
#define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6
#define SET_IPADDR_NONE(p) ((p)->ipa_type = IPADDR_NONE)
#define SET_IPADDR_V4(p) ((p)->ipa_type = IPADDR_V4)
#define SET_IPADDR_V6(p) ((p)->ipa_type = IPADDR_V6)

#define IPADDRSZ(p) \
(IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
Expand Down Expand Up @@ -165,9 +166,17 @@ static inline bool ipaddr_is_zero(const struct ipaddr *ip)
return true;
}

static inline bool ipaddr_is_same(const struct ipaddr *ip1,
const struct ipaddr *ip2)
{
return ipaddr_cmp(ip1, ip2) == 0;
}

/* clang-format off */
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
#endif
/* clang-format on */

#ifdef __cplusplus
}
Expand Down
15 changes: 12 additions & 3 deletions lib/prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,15 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
return str;
}

void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
char *buf, int buf_size)
{
if (ipaddr_is_zero(addr))
strlcpy(buf, "*", buf_size);
else
(void)snprintfrr(buf, buf_size, "%pIA", addr);
}

static ssize_t prefixhost2str(struct fbuf *fbuf, union prefixconstptr pu)
{
const struct prefix *p = pu.p;
Expand Down Expand Up @@ -1166,7 +1175,7 @@ const char *prefix_sg2str(const struct prefix_sg *sg, char *sg_str)
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];

prefix_mcast_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str));
prefix_mcast_ip_dump("<src?>", &sg->src, src_str, sizeof(src_str));
prefix_mcast_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str));
snprintf(sg_str, PREFIX_SG_STR_LEN, "(%s,%s)", src_str, grp_str);

Expand Down Expand Up @@ -1637,10 +1646,10 @@ static ssize_t printfrr_psg(struct fbuf *buf, struct printfrr_eargs *ea,
if (!sg)
return bputs(buf, "(null)");

if (sg->src.s_addr == INADDR_ANY)
if (ipaddr_is_zero(&sg->src))
mikemallin marked this conversation as resolved.
Show resolved Hide resolved
ret += bputs(buf, "(*,");
else
ret += bprintfrr(buf, "(%pI4,", &sg->src);
ret += bprintfrr(buf, "(%pIA,", &sg->src);

if (sg->grp.s_addr == INADDR_ANY)
ret += bputs(buf, "*)");
Expand Down
10 changes: 6 additions & 4 deletions lib/prefix.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ typedef enum {
/* Maximum number of VTEPs per-ES -
* XXX - temporary limit for allocating strings etc.
*/
#define ES_VTEP_MAX_CNT 10
#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * 16)
#define ES_VTEP_MAX_CNT 10
#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * IPADDR_STRING_SIZE)

#define ETHER_ADDR_STRLEN (3*ETH_ALEN)
#define ETHER_ADDR_STRLEN (3 * ETH_ALEN)
/*
* there isn't a portable ethernet address type. We define our
* own to simplify internal handling
Expand Down Expand Up @@ -282,7 +282,7 @@ struct prefix_fs {
struct prefix_sg {
uint8_t family;
uint16_t prefixlen;
struct in_addr src __attribute__((aligned(8)));
struct ipaddr src __attribute__((aligned(8)));
struct in_addr grp;
};

Expand Down Expand Up @@ -415,6 +415,8 @@ extern int str2prefix(const char *string, struct prefix *prefix);

#define PREFIX2STR_BUFFER PREFIX_STRLEN

extern void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
char *buf, int buf_size);
extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
char *buf, int buf_size);
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
Expand Down
2 changes: 1 addition & 1 deletion lib/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ int stream_put_in_addr(struct stream *s, const struct in_addr *addr)
return sizeof(uint32_t);
}

bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip)
bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip)
{
stream_putw(s, ip->ipa_type);

Expand Down
2 changes: 1 addition & 1 deletion lib/stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ extern int stream_putq(struct stream *, uint64_t);
extern int stream_putq_at(struct stream *, size_t, uint64_t);
extern int stream_put_ipv4(struct stream *, uint32_t);
extern int stream_put_in_addr(struct stream *s, const struct in_addr *addr);
extern bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip);
extern bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip);
mikemallin marked this conversation as resolved.
Show resolved Hide resolved
extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
Expand Down
12 changes: 9 additions & 3 deletions tests/lib/test_printfrr.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,19 +230,25 @@ int main(int argc, char **argv)
printchk("02:ca:fe:f0:0d:1e", "%pFXh", &pfx);

struct prefix_sg sg;
sg.src.s_addr = INADDR_ANY;
mikemallin marked this conversation as resolved.
Show resolved Hide resolved
SET_IPADDR_V4(&sg.src);
sg.src.ipaddr_v4.s_addr = INADDR_ANY;
sg.grp.s_addr = INADDR_ANY;
printchk("(*,*)", "%pPSG4", &sg);

inet_aton("192.168.1.2", &sg.src);
inet_aton("192.168.1.2", &sg.src.ipaddr_v4);
printchk("(192.168.1.2,*)", "%pPSG4", &sg);

inet_aton("224.1.2.3", &sg.grp);
printchk("(192.168.1.2,224.1.2.3)", "%pPSG4", &sg);

sg.src.s_addr = INADDR_ANY;
SET_IPADDR_NONE(&sg.src);
sg.src.ipaddr_v4.s_addr = INADDR_ANY;
printchk("(*,224.1.2.3)", "%pPSG4", &sg);

SET_IPADDR_V6(&sg.src);
inet_pton(AF_INET6, "1:2:3:4::5", &sg.src.ipaddr_v6);
printchk("(1:2:3:4::5,224.1.2.3)", "%pPSG4", &sg);

uint8_t randhex[] = { 0x12, 0x34, 0x00, 0xca, 0xfe, 0x00, 0xaa, 0x55 };

FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.8pHX", randhex));
Expand Down
2 changes: 1 addition & 1 deletion zebra/zebra_evpn_mh.c
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,7 @@ void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up)
}

static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es,
uint8_t vtep_str_size)
size_t vtep_str_size)
{
struct zebra_evpn_es_vtep *zvtep;
struct listnode *node;
Expand Down
81 changes: 50 additions & 31 deletions zebra/zebra_vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ static void zevpn_build_hash_table(void);
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
struct in_addr sip, struct in_addr mcast_grp);
static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
struct in_addr sip,
struct in_addr mcast_grp);
const struct ipaddr *sip,
const struct in_addr mcast_grp);
static struct zebra_vxlan_sg *
zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, const struct ipaddr *sip,
const struct in_addr mcast_grp);
static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);

bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
Expand Down Expand Up @@ -5891,7 +5892,10 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,

zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, IPV4_MAX_BYTELEN);
stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
/*
* There is currently no support for IPv6 VTEPs with PIM.
*/
stream_put(s, &sg->src.ipaddr_v4, IPV4_MAX_BYTELEN);
stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);

/* Write packet size. */
Expand All @@ -5914,18 +5918,26 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
{
const struct zebra_vxlan_sg *vxlan_sg = p;
uint32_t hash1;

return (jhash_2words(vxlan_sg->sg.src.s_addr,
vxlan_sg->sg.grp.s_addr, 0));
if (IS_IPADDR_V4(&vxlan_sg->sg.src)) {
return (jhash_2words(vxlan_sg->sg.src.ipaddr_v4.s_addr,
vxlan_sg->sg.grp.s_addr, 0));
} else {
hash1 = jhash_1word(vxlan_sg->sg.grp.s_addr, 0);
return jhash2(vxlan_sg->sg.src.ipaddr_v6.s6_addr32,
array_size(vxlan_sg->sg.src.ipaddr_v6.s6_addr32),
hash1);
}
}

static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
{
const struct zebra_vxlan_sg *sg1 = p1;
const struct zebra_vxlan_sg *sg2 = p2;

return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
&& (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
return (ipaddr_is_same(&sg1->sg.src, &sg2->sg.src) &&
(sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
}

static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
Expand Down Expand Up @@ -5961,7 +5973,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
{
struct zebra_vxlan_sg *vxlan_sg;
struct zebra_vxlan_sg *parent = NULL;
struct in_addr sip;
struct ipaddr sip;

vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
if (vxlan_sg)
Expand All @@ -5972,9 +5984,9 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
* 2. the XG entry is used by pimd to setup the
* vxlan-termination-mroute
*/
if (sg->src.s_addr != INADDR_ANY) {
if (!ipaddr_is_zero(&sg->src)) {
memset(&sip, 0, sizeof(sip));
parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
parent = zebra_vxlan_sg_do_ref(zvrf, &sip, sg->grp);
if (!parent)
return NULL;
}
Expand All @@ -5989,21 +6001,21 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,

static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
{
struct in_addr sip;
struct ipaddr sip;
struct zebra_vrf *zvrf;

zvrf = vrf_info_lookup(VRF_DEFAULT);

/* On SG entry deletion remove the reference to its parent XG
* entry
*/
if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
if (!ipaddr_is_zero(&vxlan_sg->sg.src)) {
memset(&sip, 0, sizeof(sip));
zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
zebra_vxlan_sg_do_deref(zvrf, &sip, vxlan_sg->sg.grp);
}

zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, vxlan_sg->sg_str,
ZEBRA_VXLAN_SG_DEL);

hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);

Expand All @@ -6014,14 +6026,15 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
}

static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
struct in_addr sip, struct in_addr mcast_grp)
const struct ipaddr *sip,
const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;

sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
sg.src = sip;
sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
if (!vxlan_sg)
Expand All @@ -6034,16 +6047,16 @@ static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
zebra_vxlan_sg_del(vxlan_sg);
}

static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
struct in_addr sip,
struct in_addr mcast_grp)
static struct zebra_vxlan_sg *
zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, const struct ipaddr *sip,
const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;

sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
sg.src = sip;
sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
if (vxlan_sg)
Expand All @@ -6052,31 +6065,37 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
return vxlan_sg;
}

void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
struct in_addr mcast_grp)
void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
struct ipaddr local_vtep_ipaddr;

if (local_vtep_ip.s_addr == INADDR_ANY
|| mcast_grp.s_addr == INADDR_ANY)
return;

zvrf = vrf_info_lookup(VRF_DEFAULT);

zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
SET_IPADDR_V4(&local_vtep_ipaddr);
local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;

zebra_vxlan_sg_do_deref(zvrf, &local_vtep_ipaddr, mcast_grp);
}

void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
struct ipaddr local_vtep_ipaddr;

if (local_vtep_ip.s_addr == INADDR_ANY
|| mcast_grp.s_addr == INADDR_ANY)
if (local_vtep_ip.s_addr == INADDR_ANY || mcast_grp.s_addr == INADDR_ANY)
return;

zvrf = vrf_info_lookup(VRF_DEFAULT);

zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
SET_IPADDR_V4(&local_vtep_ipaddr);
local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;

zebra_vxlan_sg_do_ref(zvrf, &local_vtep_ipaddr, mcast_grp);
}

static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
Expand All @@ -6086,7 +6105,7 @@ static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
/* increment the ref count against (*,G) to prevent them from being
* deleted
*/
if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
if (ipaddr_is_zero(&vxlan_sg->sg.src))
++vxlan_sg->ref_cnt;
}

Expand All @@ -6095,7 +6114,7 @@ static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;

/* decrement the dummy ref count against (*,G) to delete them */
if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
if (ipaddr_is_zero(&vxlan_sg->sg.src)) {
if (vxlan_sg->ref_cnt)
--vxlan_sg->ref_cnt;
if (!vxlan_sg->ref_cnt)
Expand Down
Loading