forked from Minki/linux
rocker: forward packets to CPU when port is joined to openvswitch
Teach rocker to forward packets to CPU when a port is joined to Open vSwitch. There is scope to later refine what is passed up as per Open vSwitch flows on a port. This does not change the behaviour of rocker ports that are not joined to Open vSwitch. Signed-off-by: Simon Horman <simon.horman@netronome.com> Acked-by: Scott Feldman <sfeldma@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a7ce45a74b
commit
8254973fa3
@ -202,6 +202,7 @@ enum {
|
|||||||
ROCKER_CTRL_IPV4_MCAST,
|
ROCKER_CTRL_IPV4_MCAST,
|
||||||
ROCKER_CTRL_IPV6_MCAST,
|
ROCKER_CTRL_IPV6_MCAST,
|
||||||
ROCKER_CTRL_DFLT_BRIDGING,
|
ROCKER_CTRL_DFLT_BRIDGING,
|
||||||
|
ROCKER_CTRL_DFLT_OVS,
|
||||||
ROCKER_CTRL_MAX,
|
ROCKER_CTRL_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -321,9 +322,21 @@ static u16 rocker_port_vlan_to_vid(const struct rocker_port *rocker_port,
|
|||||||
return ntohs(vlan_id);
|
return ntohs(vlan_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rocker_port_is_slave(const struct rocker_port *rocker_port,
|
||||||
|
const char *kind)
|
||||||
|
{
|
||||||
|
return rocker_port->bridge_dev &&
|
||||||
|
!strcmp(rocker_port->bridge_dev->rtnl_link_ops->kind, kind);
|
||||||
|
}
|
||||||
|
|
||||||
static bool rocker_port_is_bridged(const struct rocker_port *rocker_port)
|
static bool rocker_port_is_bridged(const struct rocker_port *rocker_port)
|
||||||
{
|
{
|
||||||
return !!rocker_port->bridge_dev;
|
return rocker_port_is_slave(rocker_port, "bridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port)
|
||||||
|
{
|
||||||
|
return rocker_port_is_slave(rocker_port, "openvswitch");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ROCKER_OP_FLAG_REMOVE BIT(0)
|
#define ROCKER_OP_FLAG_REMOVE BIT(0)
|
||||||
@ -3275,6 +3288,12 @@ static struct rocker_ctrl {
|
|||||||
.bridge = true,
|
.bridge = true,
|
||||||
.copy_to_cpu = true,
|
.copy_to_cpu = true,
|
||||||
},
|
},
|
||||||
|
[ROCKER_CTRL_DFLT_OVS] = {
|
||||||
|
/* pass all pkts up to CPU */
|
||||||
|
.eth_dst = zero_mac,
|
||||||
|
.eth_dst_mask = zero_mac,
|
||||||
|
.acl = true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
|
static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
|
||||||
@ -3787,11 +3806,14 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
|
|||||||
break;
|
break;
|
||||||
case BR_STATE_LEARNING:
|
case BR_STATE_LEARNING:
|
||||||
case BR_STATE_FORWARDING:
|
case BR_STATE_FORWARDING:
|
||||||
want[ROCKER_CTRL_LINK_LOCAL_MCAST] = true;
|
if (!rocker_port_is_ovsed(rocker_port))
|
||||||
|
want[ROCKER_CTRL_LINK_LOCAL_MCAST] = true;
|
||||||
want[ROCKER_CTRL_IPV4_MCAST] = true;
|
want[ROCKER_CTRL_IPV4_MCAST] = true;
|
||||||
want[ROCKER_CTRL_IPV6_MCAST] = true;
|
want[ROCKER_CTRL_IPV6_MCAST] = true;
|
||||||
if (rocker_port_is_bridged(rocker_port))
|
if (rocker_port_is_bridged(rocker_port))
|
||||||
want[ROCKER_CTRL_DFLT_BRIDGING] = true;
|
want[ROCKER_CTRL_DFLT_BRIDGING] = true;
|
||||||
|
else if (rocker_port_is_ovsed(rocker_port))
|
||||||
|
want[ROCKER_CTRL_DFLT_OVS] = true;
|
||||||
else
|
else
|
||||||
want[ROCKER_CTRL_LOCAL_ARP] = true;
|
want[ROCKER_CTRL_LOCAL_ARP] = true;
|
||||||
break;
|
break;
|
||||||
@ -5264,23 +5286,39 @@ static int rocker_port_bridge_leave(struct rocker_port *rocker_port)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rocker_port_ovs_changed(struct rocker_port *rocker_port,
|
||||||
|
struct net_device *master)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
rocker_port->bridge_dev = master;
|
||||||
|
|
||||||
|
err = rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int rocker_port_master_changed(struct net_device *dev)
|
static int rocker_port_master_changed(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct rocker_port *rocker_port = netdev_priv(dev);
|
struct rocker_port *rocker_port = netdev_priv(dev);
|
||||||
struct net_device *master = netdev_master_upper_dev_get(dev);
|
struct net_device *master = netdev_master_upper_dev_get(dev);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* There are currently three cases handled here:
|
/* N.B: Do nothing if the type of master is not supported */
|
||||||
* 1. Joining a bridge
|
if (master && master->rtnl_link_ops) {
|
||||||
* 2. Leaving a previously joined bridge
|
if (!strcmp(master->rtnl_link_ops->kind, "bridge"))
|
||||||
* 3. Other, e.g. being added to or removed from a bond or openvswitch,
|
err = rocker_port_bridge_join(rocker_port, master);
|
||||||
* in which case nothing is done
|
else if (!strcmp(master->rtnl_link_ops->kind, "openvswitch"))
|
||||||
*/
|
err = rocker_port_ovs_changed(rocker_port, master);
|
||||||
if (master && master->rtnl_link_ops &&
|
} else if (rocker_port_is_bridged(rocker_port)) {
|
||||||
!strcmp(master->rtnl_link_ops->kind, "bridge"))
|
|
||||||
err = rocker_port_bridge_join(rocker_port, master);
|
|
||||||
else if (rocker_port_is_bridged(rocker_port))
|
|
||||||
err = rocker_port_bridge_leave(rocker_port);
|
err = rocker_port_bridge_leave(rocker_port);
|
||||||
|
} else if (rocker_port_is_ovsed(rocker_port)) {
|
||||||
|
err = rocker_port_ovs_changed(rocker_port, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user