net: ipv6: add multiple interfaces to multicast routing entry
In order to save memory, a single multicast routing entry now contains configurable number of network interfaces. Signed-off-by: Konrad Derda <konrad.derda@nordicsemi.no>
This commit is contained in:
parent
97fc5ea597
commit
61dca2b8bf
|
@ -426,6 +426,15 @@ config NET_MAX_MCAST_ROUTES
|
|||
This determines how many entries can be stored in multicast
|
||||
routing table.
|
||||
|
||||
config NET_MCAST_ROUTE_MAX_IFACES
|
||||
int "Max number of network interfaces per multicast routing entry"
|
||||
default 1
|
||||
range 1 8
|
||||
depends on NET_ROUTE_MCAST
|
||||
help
|
||||
Determines how many network interfaces can be assigned to a
|
||||
single multicast route entry.
|
||||
|
||||
source "subsys/net/ip/Kconfig.tcp"
|
||||
|
||||
config NET_TEST_PROTOCOL
|
||||
|
|
|
@ -729,6 +729,55 @@ int net_route_foreach(net_route_cb_t cb, void *user_data)
|
|||
static
|
||||
struct net_route_entry_mcast route_mcast_entries[CONFIG_NET_MAX_MCAST_ROUTES];
|
||||
|
||||
static int mcast_route_iface_lookup(struct net_route_entry_mcast *entry, struct net_if *iface)
|
||||
{
|
||||
ARRAY_FOR_EACH(entry->ifaces, i) {
|
||||
if (entry->ifaces[i] == iface) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool net_route_mcast_iface_add(struct net_route_entry_mcast *entry, struct net_if *iface)
|
||||
{
|
||||
if (!net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mcast_route_iface_lookup(entry, iface) >= 0) {
|
||||
/* Interface is already added */
|
||||
return true;
|
||||
}
|
||||
|
||||
ARRAY_FOR_EACH(entry->ifaces, i) {
|
||||
if (entry->ifaces[i] == NULL) {
|
||||
entry->ifaces[i] = iface;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* There are no empty slots */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool net_route_mcast_iface_del(struct net_route_entry_mcast *entry,
|
||||
struct net_if *iface)
|
||||
{
|
||||
int pos = mcast_route_iface_lookup(entry, iface);
|
||||
|
||||
if (pos < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entry->ifaces[pos] = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int net_route_mcast_forward_packet(struct net_pkt *pkt,
|
||||
const struct net_ipv6_hdr *hdr)
|
||||
{
|
||||
|
@ -737,34 +786,34 @@ int net_route_mcast_forward_packet(struct net_pkt *pkt,
|
|||
ARRAY_FOR_EACH_PTR(route_mcast_entries, route) {
|
||||
struct net_pkt *pkt_cpy = NULL;
|
||||
|
||||
if (!route->is_used) {
|
||||
if (!route->is_used ||
|
||||
!net_ipv6_is_prefix(hdr->dst, route->group.s6_addr, route->prefix_len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!net_if_flag_is_set(route->iface,
|
||||
NET_IF_FORWARD_MULTICASTS) ||
|
||||
!net_ipv6_is_prefix(hdr->dst,
|
||||
route->group.s6_addr,
|
||||
route->prefix_len) ||
|
||||
(pkt->iface == route->iface)) {
|
||||
continue;
|
||||
}
|
||||
ARRAY_FOR_EACH(route->ifaces, i) {
|
||||
if (!route->ifaces[i] || pkt->iface == route->ifaces[i] ||
|
||||
!net_if_flag_is_set(route->ifaces[i], NET_IF_FORWARD_MULTICASTS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pkt_cpy = net_pkt_shallow_clone(pkt, K_NO_WAIT);
|
||||
pkt_cpy = net_pkt_shallow_clone(pkt, K_NO_WAIT);
|
||||
|
||||
if (pkt_cpy == NULL) {
|
||||
err--;
|
||||
continue;
|
||||
}
|
||||
if (pkt_cpy == NULL) {
|
||||
err--;
|
||||
continue;
|
||||
}
|
||||
|
||||
net_pkt_set_forwarding(pkt_cpy, true);
|
||||
net_pkt_set_iface(pkt_cpy, route->iface);
|
||||
net_pkt_set_forwarding(pkt_cpy, true);
|
||||
net_pkt_set_orig_iface(pkt_cpy, pkt->iface);
|
||||
net_pkt_set_iface(pkt_cpy, route->ifaces[i]);
|
||||
|
||||
if (net_send_data(pkt_cpy) >= 0) {
|
||||
++ret;
|
||||
} else {
|
||||
net_pkt_unref(pkt_cpy);
|
||||
--err;
|
||||
if (net_send_data(pkt_cpy) >= 0) {
|
||||
++ret;
|
||||
} else {
|
||||
net_pkt_unref(pkt_cpy);
|
||||
--err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,8 +861,12 @@ struct net_route_entry_mcast *net_route_mcast_add(struct net_if *iface,
|
|||
if (!route->is_used) {
|
||||
net_ipaddr_copy(&route->group, group);
|
||||
|
||||
ARRAY_FOR_EACH(route->ifaces, i) {
|
||||
route->ifaces[i] = NULL;
|
||||
}
|
||||
|
||||
route->prefix_len = prefix_len;
|
||||
route->iface = iface;
|
||||
route->ifaces[0] = iface;
|
||||
route->is_used = true;
|
||||
|
||||
net_ipv6_nbr_unlock();
|
||||
|
@ -1016,5 +1069,8 @@ void net_route_init(void)
|
|||
NET_DBG("Allocated %d nexthop entries (%zu bytes)",
|
||||
CONFIG_NET_MAX_NEXTHOPS, sizeof(net_route_nexthop_pool));
|
||||
|
||||
#if defined(CONFIG_NET_ROUTE_MCAST)
|
||||
memset(route_mcast_entries, 0, sizeof(route_mcast_entries));
|
||||
#endif
|
||||
k_work_init_delayable(&route_lifetime_timer, route_lifetime_timeout);
|
||||
}
|
||||
|
|
|
@ -183,12 +183,13 @@ typedef void (*net_route_cb_t)(struct net_route_entry *entry,
|
|||
*/
|
||||
int net_route_foreach(net_route_cb_t cb, void *user_data);
|
||||
|
||||
#if defined(CONFIG_NET_ROUTE_MCAST)
|
||||
/**
|
||||
* @brief Multicast route entry.
|
||||
*/
|
||||
struct net_route_entry_mcast {
|
||||
/** Network interface for the route. */
|
||||
struct net_if *iface;
|
||||
/** Network interfaces for the route. */
|
||||
struct net_if *ifaces[CONFIG_NET_MCAST_ROUTE_MAX_IFACES];
|
||||
|
||||
/** Extra routing engine specific data */
|
||||
void *data;
|
||||
|
@ -205,6 +206,9 @@ struct net_route_entry_mcast {
|
|||
/** IPv6 multicast group prefix length. */
|
||||
uint8_t prefix_len;
|
||||
};
|
||||
#else
|
||||
struct net_route_entry_mcast;
|
||||
#endif
|
||||
|
||||
typedef void (*net_route_mcast_cb_t)(struct net_route_entry_mcast *entry,
|
||||
void *user_data);
|
||||
|
@ -268,6 +272,27 @@ bool net_route_mcast_del(struct net_route_entry_mcast *route);
|
|||
struct net_route_entry_mcast *
|
||||
net_route_mcast_lookup(struct in6_addr *group);
|
||||
|
||||
/**
|
||||
* @brief Add an interface to multicast routing entry.
|
||||
*
|
||||
* @param entry Multicast routing entry.
|
||||
* @param iface Network interface to be added.
|
||||
*
|
||||
* @return True if the interface was added or found on the
|
||||
* list, false otherwise.
|
||||
*/
|
||||
bool net_route_mcast_iface_add(struct net_route_entry_mcast *entry, struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Delete an interface from multicast routing entry.
|
||||
*
|
||||
* @param entry Multicast routing entry.
|
||||
* @param iface Network interface to be deleted.
|
||||
*
|
||||
* @return True if entry was deleted, false otherwise.
|
||||
*/
|
||||
bool net_route_mcast_iface_del(struct net_route_entry_mcast *entry, struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Return a route to destination via some intermediate host.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue