forked from Mirror/frr
pimd: fuse source_new() and add_source_by_addr()
This makes a lot more sense semantically (and matches the way groups are handled.) Also allows placing additional restrictions on source creation (e.g. limit on number of sources or ACLs.) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
a1a4295ade
commit
5421bf8f1d
|
@ -191,6 +191,10 @@ struct igmp_group *find_group_by_addr(struct igmp_sock *igmp,
|
||||||
struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
|
struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
|
||||||
struct in_addr group_addr);
|
struct in_addr group_addr);
|
||||||
|
|
||||||
|
struct igmp_source *igmp_get_source_by_addr(struct igmp_group *group,
|
||||||
|
struct in_addr src_addr,
|
||||||
|
bool *created);
|
||||||
|
|
||||||
void igmp_group_delete_empty_include(struct igmp_group *group);
|
void igmp_group_delete_empty_include(struct igmp_group *group);
|
||||||
|
|
||||||
void igmp_startup_mode_on(struct igmp_sock *igmp);
|
void igmp_startup_mode_on(struct igmp_sock *igmp);
|
||||||
|
@ -198,9 +202,6 @@ void igmp_startup_mode_on(struct igmp_sock *igmp);
|
||||||
void igmp_group_timer_on(struct igmp_group *group, long interval_msec,
|
void igmp_group_timer_on(struct igmp_group *group, long interval_msec,
|
||||||
const char *ifname);
|
const char *ifname);
|
||||||
|
|
||||||
struct igmp_source *source_new(struct igmp_group *group,
|
|
||||||
struct in_addr src_addr);
|
|
||||||
|
|
||||||
void igmp_send_query(int igmp_version, struct igmp_group *group, int fd,
|
void igmp_send_query(int igmp_version, struct igmp_group *group, int fd,
|
||||||
const char *ifname, char *query_buf, int query_buf_size,
|
const char *ifname, char *query_buf, int query_buf_size,
|
||||||
int num_sources, struct in_addr dst_addr,
|
int num_sources, struct in_addr dst_addr,
|
||||||
|
|
|
@ -441,11 +441,18 @@ struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct igmp_source *source_new(struct igmp_group *group,
|
struct igmp_source *igmp_get_source_by_addr(struct igmp_group *group,
|
||||||
struct in_addr src_addr)
|
struct in_addr src_addr, bool *new)
|
||||||
{
|
{
|
||||||
struct igmp_source *src;
|
struct igmp_source *src;
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
*new = false;
|
||||||
|
|
||||||
|
src = igmp_find_source_by_addr(group, src_addr);
|
||||||
|
if (src)
|
||||||
|
return src;
|
||||||
|
|
||||||
if (PIM_DEBUG_IGMP_TRACE) {
|
if (PIM_DEBUG_IGMP_TRACE) {
|
||||||
char group_str[INET_ADDRSTRLEN];
|
char group_str[INET_ADDRSTRLEN];
|
||||||
char source_str[INET_ADDRSTRLEN];
|
char source_str[INET_ADDRSTRLEN];
|
||||||
|
@ -472,23 +479,6 @@ struct igmp_source *source_new(struct igmp_group *group,
|
||||||
|
|
||||||
/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
|
/* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
|
||||||
igmp_anysource_forward_stop(group);
|
igmp_anysource_forward_stop(group);
|
||||||
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp,
|
|
||||||
struct igmp_group *group,
|
|
||||||
struct in_addr src_addr)
|
|
||||||
{
|
|
||||||
struct igmp_source *src;
|
|
||||||
|
|
||||||
src = igmp_find_source_by_addr(group, src_addr);
|
|
||||||
if (src) {
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
|
|
||||||
src = source_new(group, src_addr);
|
|
||||||
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,10 +530,9 @@ static void allow(struct igmp_sock *igmp, struct in_addr from,
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
source = add_source_by_addr(igmp, group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, NULL);
|
||||||
if (!source) {
|
if (!source)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
RFC 3376: 6.4.1. Reception of Current-State Records
|
RFC 3376: 6.4.1. Reception of Current-State Records
|
||||||
|
@ -585,18 +574,21 @@ static void isex_excl(struct igmp_group *group, int num_sources,
|
||||||
/* scan received sources (A) */
|
/* scan received sources (A) */
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* E.2: lookup reported source from (A) in (X,Y) */
|
/* E.2: lookup reported source from (A) in (X,Y) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!new) {
|
||||||
/* E.3: if found, clear deletion flag: (X*A) or (Y*A) */
|
/* E.3: if found, clear deletion flag: (X*A) or (Y*A) */
|
||||||
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
||||||
} else {
|
} else {
|
||||||
/* E.4: if not found, create source with timer=GMI:
|
/* E.4: if not found, create source with timer=GMI:
|
||||||
* (A-X-Y) */
|
* (A-X-Y) */
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
assert(!source->t_source_timer); /* timer == 0 */
|
assert(!source->t_source_timer); /* timer == 0 */
|
||||||
igmp_source_reset_gmi(group, source);
|
igmp_source_reset_gmi(group, source);
|
||||||
assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
|
assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
|
||||||
|
@ -637,18 +629,21 @@ static void isex_incl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* I.2: lookup reported source (B) */
|
/* I.2: lookup reported source (B) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!new) {
|
||||||
/* I.3: if found, clear deletion flag (A*B) */
|
/* I.3: if found, clear deletion flag (A*B) */
|
||||||
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
||||||
} else {
|
} else {
|
||||||
/* I.4: if not found, create source with timer=0 (B-A)
|
/* I.4: if not found, create source with timer=0 (B-A)
|
||||||
*/
|
*/
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
assert(!source->t_source_timer); /* (B-A) timer=0 */
|
assert(!source->t_source_timer); /* (B-A) timer=0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,18 +709,19 @@ static void toin_incl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* Lookup reported source (B) */
|
/* Lookup reported source (B) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!new) {
|
||||||
/* If found, clear SEND flag (A*B) */
|
/* If found, clear SEND flag (A*B) */
|
||||||
IGMP_SOURCE_DONT_SEND(source->source_flags);
|
IGMP_SOURCE_DONT_SEND(source->source_flags);
|
||||||
--num_sources_tosend;
|
--num_sources_tosend;
|
||||||
} else {
|
|
||||||
/* If not found, create new source */
|
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (B)=GMI */
|
/* (B)=GMI */
|
||||||
|
@ -751,21 +747,20 @@ static void toin_excl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* Lookup reported source (A) */
|
/* Lookup reported source (A) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!source)
|
||||||
if (source->t_source_timer) {
|
continue;
|
||||||
/* If found and timer running, clear SEND flag
|
|
||||||
* (X*A) */
|
if (source->t_source_timer) {
|
||||||
IGMP_SOURCE_DONT_SEND(source->source_flags);
|
/* If found and timer running, clear SEND flag
|
||||||
--num_sources_tosend;
|
* (X*A) */
|
||||||
}
|
IGMP_SOURCE_DONT_SEND(source->source_flags);
|
||||||
} else {
|
--num_sources_tosend;
|
||||||
/* If not found, create new source */
|
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (A)=GMI */
|
/* (A)=GMI */
|
||||||
|
@ -835,22 +830,18 @@ static void toex_incl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* Lookup reported source (B) */
|
/* Lookup reported source (B) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!new) {
|
||||||
/* If found, clear deletion flag: (A*B) */
|
/* If found, clear deletion flag: (A*B) */
|
||||||
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
||||||
/* and set SEND flag (A*B) */
|
/* and set SEND flag (A*B) */
|
||||||
IGMP_SOURCE_DO_SEND(source->source_flags);
|
IGMP_SOURCE_DO_SEND(source->source_flags);
|
||||||
++num_sources_tosend;
|
++num_sources_tosend;
|
||||||
} else {
|
|
||||||
/* If source not found, create source with timer=0:
|
|
||||||
* (B-A)=0 */
|
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
assert(!source->t_source_timer); /* (B-A) timer=0 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* Scan received sources (B) */
|
} /* Scan received sources (B) */
|
||||||
|
@ -895,12 +886,16 @@ static void toex_excl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* lookup reported source (A) in known sources (X,Y) */
|
/* lookup reported source (A) in known sources (X,Y) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (source) {
|
if (!source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!new) {
|
||||||
/* if found, clear off DELETE flag from reported source
|
/* if found, clear off DELETE flag from reported source
|
||||||
* (A) */
|
* (A) */
|
||||||
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
IGMP_SOURCE_DONT_DELETE(source->source_flags);
|
||||||
|
@ -908,7 +903,6 @@ static void toex_excl(struct igmp_group *group, int num_sources,
|
||||||
/* if not found, create source with Group Timer:
|
/* if not found, create source with Group Timer:
|
||||||
* (A-X-Y)=Group Timer */
|
* (A-X-Y)=Group Timer */
|
||||||
long group_timer_msec;
|
long group_timer_msec;
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
|
|
||||||
assert(!source->t_source_timer); /* timer == 0 */
|
assert(!source->t_source_timer); /* timer == 0 */
|
||||||
group_timer_msec = igmp_group_timer_remain_msec(group);
|
group_timer_msec = igmp_group_timer_remain_msec(group);
|
||||||
|
@ -1404,16 +1398,19 @@ static void block_excl(struct igmp_group *group, int num_sources,
|
||||||
for (i = 0; i < num_sources; ++i) {
|
for (i = 0; i < num_sources; ++i) {
|
||||||
struct igmp_source *source;
|
struct igmp_source *source;
|
||||||
struct in_addr *src_addr;
|
struct in_addr *src_addr;
|
||||||
|
bool new;
|
||||||
|
|
||||||
src_addr = sources + i;
|
src_addr = sources + i;
|
||||||
|
|
||||||
/* lookup reported source (A) in known sources (X,Y) */
|
/* lookup reported source (A) in known sources (X,Y) */
|
||||||
source = igmp_find_source_by_addr(group, *src_addr);
|
source = igmp_get_source_by_addr(group, *src_addr, &new);
|
||||||
if (!source) {
|
if (!source)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (new) {
|
||||||
/* 3: if not found, create source with Group Timer:
|
/* 3: if not found, create source with Group Timer:
|
||||||
* (A-X-Y)=Group Timer */
|
* (A-X-Y)=Group Timer */
|
||||||
long group_timer_msec;
|
long group_timer_msec;
|
||||||
source = source_new(group, *src_addr);
|
|
||||||
|
|
||||||
assert(!source->t_source_timer); /* timer == 0 */
|
assert(!source->t_source_timer); /* timer == 0 */
|
||||||
group_timer_msec = igmp_group_timer_remain_msec(group);
|
group_timer_msec = igmp_group_timer_remain_msec(group);
|
||||||
|
|
|
@ -474,7 +474,7 @@ void igmp_anysource_forward_start(struct pim_instance *pim,
|
||||||
assert(group->group_filtermode_isexcl);
|
assert(group->group_filtermode_isexcl);
|
||||||
assert(listcount(group->group_source_list) < 1);
|
assert(listcount(group->group_source_list) < 1);
|
||||||
|
|
||||||
source = source_new(group, src_addr);
|
source = igmp_get_source_by_addr(group, src_addr, NULL);
|
||||||
if (!source) {
|
if (!source) {
|
||||||
zlog_warn("%s: Failure to create * source", __func__);
|
zlog_warn("%s: Failure to create * source", __func__);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue