Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da885b61 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlxsw-mc-route-offload'



Jiri Pirko says:

====================
mlxsw: Add support for partial multicast route offload

Yotam says:

Previous patchset introduced support for offloading multicast MFC routes to
the Spectrum hardware. As described in that patchset, no partial offloading
is supported, i.e if a route has one output interface which is not a valid
offloadable device (e.g. pimreg device, dummy device, management NIC), the
route is trapped to the CPU and the forwarding is done in slow-path.

Add support for partial offloading of multicast routes, by letting the
hardware to forward the packet to all the in-hardware devices, while the
kernel ipmr module will continue forwarding to all other interfaces.

Similarly to the bridge, the kernel ipmr module will forward a marked
packet to an interface only if the interface has a different parent ID than
the packet's ingress interfaces.

The first patch introduces the offload_mr_fwd_mark skb field, which can be
used by offloading drivers to indicate that a packet had already gone
through multicast forwarding in hardware, similarly to the offload_fwd_mark
field that indicates that a packet had already gone through L2 forwarding
in hardware.

Patches 2 and 3 change the ipmr module to not forward packets that had
already been forwarded by the hardware, i.e. packets that are marked with
offload_mr_fwd_mark and the ingress VIF shares the same parent ID with the
egress VIF.

Patches 4, 5, 6 and 7 add the support in the mlxsw Spectrum driver for trap
and forward routes, while marking the trapped packets with the
offload_mr_fwd_mark.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a047fbae f60c2549
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -676,6 +676,7 @@ enum mlxsw_afa_trapdisc_trap_action {
MLXSW_ITEM32(afa, trapdisc, trap_action, 0x00, 24, 4);

enum mlxsw_afa_trapdisc_forward_action {
	MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD = 1,
	MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD = 3,
};

@@ -729,6 +730,22 @@ int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id)
}
EXPORT_SYMBOL(mlxsw_afa_block_append_trap);

int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
					    u16 trap_id)
{
	char *act = mlxsw_afa_block_append_action(block,
						  MLXSW_AFA_TRAPDISC_CODE,
						  MLXSW_AFA_TRAPDISC_SIZE);

	if (!act)
		return -ENOBUFS;
	mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP,
				MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD,
				trap_id);
	return 0;
}
EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);

/* Forwarding Action
 * -----------------
 * Forwarding Action can be used to implement Policy Based Switching (PBS)
+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
					    u16 trap_id);
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
			       u8 local_port, bool in_port);
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
+13 −0
Original line number Diff line number Diff line
@@ -3312,6 +3312,14 @@ static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u8 local_port,
	return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
}

static void mlxsw_sp_rx_listener_mr_mark_func(struct sk_buff *skb,
					      u8 local_port, void *priv)
{
	skb->offload_mr_fwd_mark = 1;
	skb->offload_fwd_mark = 1;
	return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
}

static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port,
					     void *priv)
{
@@ -3355,6 +3363,10 @@ static void mlxsw_sp_rx_listener_sample_func(struct sk_buff *skb, u8 local_port,
	MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action,	\
		_is_ctrl, SP_##_trap_group, DISCARD)

#define MLXSW_SP_RXL_MR_MARK(_trap_id, _action, _trap_group, _is_ctrl)	\
	MLXSW_RXL(mlxsw_sp_rx_listener_mr_mark_func, _trap_id, _action,	\
		_is_ctrl, SP_##_trap_group, DISCARD)

#define MLXSW_SP_EVENTL(_func, _trap_id)		\
	MLXSW_EVENTL(_func, _trap_id, SP_EVENT)

@@ -3425,6 +3437,7 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
	MLXSW_SP_RXL_MARK(IPV4_PIM, TRAP_TO_CPU, PIM, false),
	MLXSW_SP_RXL_MARK(RPF, TRAP_TO_CPU, RPF, false),
	MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false),
	MLXSW_SP_RXL_MR_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false),
};

static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
+8 −9
Original line number Diff line number Diff line
@@ -114,9 +114,9 @@ static bool mlxsw_sp_mr_vif_valid(const struct mlxsw_sp_mr_vif *vif)
	return mlxsw_sp_mr_vif_regular(vif) && vif->dev && vif->rif;
}

static bool mlxsw_sp_mr_vif_rif_invalid(const struct mlxsw_sp_mr_vif *vif)
static bool mlxsw_sp_mr_vif_exists(const struct mlxsw_sp_mr_vif *vif)
{
	return mlxsw_sp_mr_vif_regular(vif) && vif->dev && !vif->rif;
	return vif->dev;
}

static bool
@@ -182,14 +182,13 @@ mlxsw_sp_mr_route_action(const struct mlxsw_sp_mr_route *mr_route)
	if (!mlxsw_sp_mr_route_valid_evifs_num(mr_route))
		return MLXSW_SP_MR_ROUTE_ACTION_TRAP;

	/* If either one of the eVIFs is not regular (VIF of type pimreg or
	 * tunnel) or one of the VIFs has no matching RIF, trap the packet.
	/* If one of the eVIFs has no RIF, trap-and-forward the route as there
	 * is some more routing to do in software too.
	 */
	list_for_each_entry(rve, &mr_route->evif_list, route_node) {
		if (!mlxsw_sp_mr_vif_regular(rve->mr_vif) ||
		    mlxsw_sp_mr_vif_rif_invalid(rve->mr_vif))
			return MLXSW_SP_MR_ROUTE_ACTION_TRAP;
	}
	list_for_each_entry(rve, &mr_route->evif_list, route_node)
		if (mlxsw_sp_mr_vif_exists(rve->mr_vif) && !rve->mr_vif->rif)
			return MLXSW_SP_MR_ROUTE_ACTION_TRAP_AND_FORWARD;

	return MLXSW_SP_MR_ROUTE_ACTION_FORWARD;
}

+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
enum mlxsw_sp_mr_route_action {
	MLXSW_SP_MR_ROUTE_ACTION_FORWARD,
	MLXSW_SP_MR_ROUTE_ACTION_TRAP,
	MLXSW_SP_MR_ROUTE_ACTION_TRAP_AND_FORWARD,
};

enum mlxsw_sp_mr_route_prio {
Loading