#include "byte-order.h"
#include "coverage.h"
#include "hash.h"
-#include "list.h"
-#include "poll-loop.h"
+#include "openvswitch/list.h"
+#include "openvswitch/poll-loop.h"
#include "timeval.h"
#include "entropy.h"
#include "unaligned.h"
group_get_lru(const struct mcast_snooping *ms, struct mcast_group **grp)
OVS_REQ_RDLOCK(ms->rwlock)
{
- if (!list_is_empty(&ms->group_lru)) {
+ if (!ovs_list_is_empty(&ms->group_lru)) {
*grp = mcast_group_from_lru_node(ms->group_lru.next);
return true;
} else {
ms = xmalloc(sizeof *ms);
hmap_init(&ms->table);
- list_init(&ms->group_lru);
- list_init(&ms->mrouter_lru);
- list_init(&ms->fport_list);
- list_init(&ms->rport_list);
+ ovs_list_init(&ms->group_lru);
+ ovs_list_init(&ms->mrouter_lru);
+ ovs_list_init(&ms->fport_list);
+ ovs_list_init(&ms->rport_list);
ms->secret = random_uint32();
ms->idle_time = MCAST_ENTRY_DEFAULT_IDLE_TIME;
ms->max_entries = MCAST_DEFAULT_MAX_ENTRIES;
b = mcast_group_bundle_lookup(ms, grp, port);
if (b) {
- list_remove(&b->bundle_node);
+ ovs_list_remove(&b->bundle_node);
} else {
b = xmalloc(sizeof *b);
- list_init(&b->bundle_node);
+ ovs_list_init(&b->bundle_node);
b->port = port;
+ ms->need_revalidate = true;
}
b->expires = time_now() + idle_time;
- list_push_back(&grp->bundle_lru, &b->bundle_node);
+ ovs_list_push_back(&grp->bundle_lru, &b->bundle_node);
return b;
}
static bool
mcast_group_has_bundles(struct mcast_group *grp)
{
- return !list_is_empty(&grp->bundle_lru);
+ return !ovs_list_is_empty(&grp->bundle_lru);
}
/* Delete 'grp' from the 'ms' hash table.
mcast_snooping_flush_group__(struct mcast_snooping *ms,
struct mcast_group *grp)
{
- ovs_assert(list_is_empty(&grp->bundle_lru));
+ ovs_assert(ovs_list_is_empty(&grp->bundle_lru));
hmap_remove(&ms->table, &grp->hmap_node);
- list_remove(&grp->group_node);
+ ovs_list_remove(&grp->group_node);
free(grp);
}
LIST_FOR_EACH (b, bundle_node, &grp->bundle_lru) {
if (b->port == port) {
- list_remove(&b->bundle_node);
+ ovs_list_remove(&b->bundle_node);
free(b);
return true;
}
if (b->expires > timenow) {
break;
}
- list_remove(&b->bundle_node);
+ ovs_list_remove(&b->bundle_node);
free(b);
expired++;
}
hmap_insert(&ms->table, &grp->hmap_node, hash);
grp->addr = *addr;
grp->vlan = vlan;
- list_init(&grp->bundle_lru);
+ ovs_list_init(&grp->bundle_lru);
learned = true;
ms->need_revalidate = true;
COVERAGE_INC(mcast_snooping_learned);
} else {
- list_remove(&grp->group_node);
+ ovs_list_remove(&grp->group_node);
}
mcast_group_insert_bundle(ms, grp, port, ms->idle_time);
/* Mark 'grp' as recently used. */
- list_push_back(&ms->group_lru, &grp->group_node);
+ ovs_list_push_back(&ms->group_lru, &grp->group_node);
return learned;
}
struct mcast_mrouter_bundle **m)
OVS_REQ_RDLOCK(ms->rwlock)
{
- if (!list_is_empty(&ms->mrouter_lru)) {
+ if (!ovs_list_is_empty(&ms->mrouter_lru)) {
*m = mcast_mrouter_from_lru_node(ms->mrouter_lru.next);
return true;
} else {
mrouter = mcast_snooping_mrouter_lookup(ms, vlan, port);
if (mrouter) {
- list_remove(&mrouter->mrouter_node);
+ ovs_list_remove(&mrouter->mrouter_node);
} else {
mrouter = xmalloc(sizeof *mrouter);
mrouter->vlan = vlan;
}
mrouter->expires = time_now() + MCAST_MROUTER_PORT_IDLE_TIME;
- list_push_back(&ms->mrouter_lru, &mrouter->mrouter_node);
+ ovs_list_push_back(&ms->mrouter_lru, &mrouter->mrouter_node);
return ms->need_revalidate;
}
static void
mcast_snooping_flush_mrouter(struct mcast_mrouter_bundle *mrouter)
{
- list_remove(&mrouter->mrouter_node);
+ ovs_list_remove(&mrouter->mrouter_node);
free(mrouter);
}
\f
mcast_snooping_port_get(const struct ovs_list *list,
struct mcast_port_bundle **f)
{
- if (!list_is_empty(list)) {
+ if (!ovs_list_is_empty(list)) {
*f = mcast_port_from_list_node(list->next);
return true;
} else {
pbundle = xmalloc(sizeof *pbundle);
pbundle->port = port;
- list_insert(list, &pbundle->node);
+ ovs_list_insert(list, &pbundle->node);
}
static void
mcast_snooping_flush_port(struct mcast_port_bundle *pbundle)
{
- list_remove(&pbundle->node);
+ ovs_list_remove(&pbundle->node);
free(pbundle);
}
long long int mrouter_msec;
long long int msec = 0;
- if (!list_is_empty(&ms->group_lru)) {
+ if (!ovs_list_is_empty(&ms->group_lru)) {
grp = mcast_group_from_lru_node(ms->group_lru.next);
bundle = mcast_group_bundle_from_lru_node(grp->bundle_lru.next);
msec = bundle->expires * 1000LL;
}
- if (!list_is_empty(&ms->mrouter_lru)) {
+ if (!ovs_list_is_empty(&ms->mrouter_lru)) {
mrouter = mcast_mrouter_from_lru_node(ms->mrouter_lru.next);
mrouter_msec = mrouter->expires * 1000LL;
msec = msec ? MIN(msec, mrouter_msec) : mrouter_msec;
mcast_snooping_wait__(ms);
ovs_rwlock_unlock(&ms->rwlock);
}
+
+void
+mcast_snooping_flush_bundle(struct mcast_snooping *ms, void *port)
+{
+ struct mcast_group *g, *next_g;
+ struct mcast_mrouter_bundle *m, *next_m;
+
+ if (!mcast_snooping_enabled(ms)) {
+ return;
+ }
+
+ ovs_rwlock_wrlock(&ms->rwlock);
+ LIST_FOR_EACH_SAFE (g, next_g, group_node, &ms->group_lru) {
+ if (mcast_group_delete_bundle(ms, g, port)) {
+ ms->need_revalidate = true;
+
+ if (!mcast_group_has_bundles(g)) {
+ mcast_snooping_flush_group__(ms, g);
+ }
+ }
+ }
+
+ LIST_FOR_EACH_SAFE (m, next_m, mrouter_node, &ms->mrouter_lru) {
+ if (m->port == port) {
+ mcast_snooping_flush_mrouter(m);
+ ms->need_revalidate = true;
+ }
+ }
+
+ ovs_rwlock_unlock(&ms->rwlock);
+}