Skip to content

Commit cba45a0

Browse files
committed
port: prevent disabling forced promiscuous and allmulti modes
When a port MAC filter table reaches its hardware limit or if the driver does not support individual address filtering, the code falls back to enabling promisc or allmulti mode to ensure all required traffic is still received. However, other code paths that manage these modes were unaware of this fallback mechanism and could inadvertently disable them, breaking MAC address filtering. Introduce two new interface state flags to track when promisc or allmulti modes have been force-enabled due to MAC filter overflow/unsupported. The port_promisc_set() and port_allmulti_set() functions now check these forced states and refuse to modify the hardware state when the mode is required for filtering. Update the CLI to distinguish between user-requested and filter-forced modes by displaying "promisc(forced)" or "allmulti(forced)" when applicable. Signed-off-by: Robin Jarry <[email protected]>
1 parent 5ed23e6 commit cba45a0

3 files changed

Lines changed: 28 additions & 11 deletions

File tree

modules/infra/api/gr_infra.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ typedef enum : uint16_t {
3535
// Interface state flags
3636
typedef enum : uint16_t {
3737
GR_IFACE_S_RUNNING = GR_BIT16(0),
38+
GR_IFACE_S_PROMISC_FORCED = GR_BIT16(1),
39+
GR_IFACE_S_ALLMULTI_FORCED = GR_BIT16(2),
3840
} gr_iface_state_t;
3941

4042
// Interface reconfig attributes

modules/infra/cli/iface.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,13 @@ static ssize_t iface_flags_format(char *buf, size_t len, const struct gr_iface *
124124
SAFE_BUF(snprintf, len, "down");
125125
if (iface->state & GR_IFACE_S_RUNNING)
126126
SAFE_BUF(snprintf, len, " running");
127-
if (iface->flags & GR_IFACE_F_PROMISC)
127+
if (iface->state & GR_IFACE_S_PROMISC_FORCED)
128+
SAFE_BUF(snprintf, len, " promisc(forced)");
129+
else if (iface->flags & GR_IFACE_F_PROMISC)
128130
SAFE_BUF(snprintf, len, " promisc");
129-
if (iface->flags & GR_IFACE_F_ALLMULTI)
131+
if (iface->state & GR_IFACE_S_ALLMULTI_FORCED)
132+
SAFE_BUF(snprintf, len, " allmulti(forced)");
133+
else if (iface->flags & GR_IFACE_F_ALLMULTI)
130134
SAFE_BUF(snprintf, len, " allmulti");
131135
if (iface->flags & GR_IFACE_F_PACKET_TRACE)
132136
SAFE_BUF(snprintf, len, " tracing");

modules/infra/control/port.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ static int port_promisc_set(struct iface *iface, bool enabled) {
198198
struct iface_info_port *p = iface_info_port(iface);
199199
int ret;
200200

201-
if (enabled)
201+
if (p->ucast_filter.flags & MAC_FILTER_F_ALL)
202+
ret = 0; // promisc is forced to filter unicast addresses, leave it as-is
203+
else if (enabled)
202204
ret = rte_eth_promiscuous_enable(p->port_id);
203205
else
204206
ret = rte_eth_promiscuous_disable(p->port_id);
@@ -224,7 +226,9 @@ static int port_allmulti_set(struct iface *iface, bool enabled) {
224226
struct iface_info_port *p = iface_info_port(iface);
225227
int ret;
226228

227-
if (enabled)
229+
if (p->mcast_filter.flags & MAC_FILTER_F_ALL)
230+
ret = 0; // allmulti is forced to filter multicast addresses, leave it as-is
231+
else if (enabled)
228232
ret = rte_eth_allmulticast_enable(p->port_id);
229233
else
230234
ret = rte_eth_allmulticast_disable(p->port_id);
@@ -562,12 +566,16 @@ static int port_mac_add(struct iface *iface, const struct rte_ether_addr *mac) {
562566

563567
// promisc and allmulti enable is a noop if already enabled
564568
if (multicast)
565-
ret = rte_eth_allmulticast_enable(port->port_id);
569+
ret = port_allmulti_set(iface, true);
566570
else
567-
ret = rte_eth_promiscuous_enable(port->port_id);
571+
ret = port_promisc_set(iface, true);
568572

569-
if (ret == 0)
573+
if (ret == 0) {
570574
filter->flags |= MAC_FILTER_F_ALL;
575+
iface->state |= multicast ?
576+
GR_IFACE_S_ALLMULTI_FORCED :
577+
GR_IFACE_S_PROMISC_FORCED;
578+
}
571579
}
572580

573581
if (ret < 0) {
@@ -638,10 +646,13 @@ static int port_mac_del(struct iface *iface, const struct rte_ether_addr *mac) {
638646
return 0;
639647
filter->flags = 0;
640648
filter->hw_limit = 0;
641-
if (multicast)
642-
ret = rte_eth_allmulticast_disable(port->port_id);
643-
else
644-
ret = rte_eth_promiscuous_disable(port->port_id);
649+
if (multicast) {
650+
iface->state &= ~GR_IFACE_S_ALLMULTI_FORCED;
651+
ret = port_allmulti_set(iface, false);
652+
} else {
653+
iface->state &= ~GR_IFACE_S_PROMISC_FORCED;
654+
ret = port_promisc_set(iface, false);
655+
}
645656
if (ret < 0)
646657
LOG(WARNING,
647658
"%s: %s disable: %s",

0 commit comments

Comments
 (0)