lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 15 Mar 2023 14:43:26 +0000
From:   Edward Cree <ecree.xilinx@...il.com>
To:     Michal Swiatkowski <michal.swiatkowski@...ux.intel.com>,
        edward.cree@....com
Cc:     linux-net-drivers@....com, davem@...emloft.net, kuba@...nel.org,
        pabeni@...hat.com, edumazet@...gle.com, netdev@...r.kernel.org,
        habetsm.xilinx@...il.com
Subject: Re: [PATCH net-next 5/5] sfc: add offloading of 'foreign' TC (decap)
 rules

On 15/03/2023 10:11, Michal Swiatkowski wrote:
> On Tue, Mar 14, 2023 at 05:35:25PM +0000, edward.cree@....com wrote:
>> +int efx_mae_check_encap_type_supported(struct efx_nic *efx, enum efx_encap_type typ)
>> +{
>> +	unsigned int bit;
>> +
>> +	switch (typ & EFX_ENCAP_TYPES_MASK) {
> In 3/5 You ommited EFX_ENCAP_TYPE_NVGRE, was it intetional?

No, I'll go back and add it.

>> +enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
>> +{
>> +	if (netif_is_vxlan(net_dev))
>> +		return EFX_ENCAP_TYPE_VXLAN;
>> +	if (netif_is_geneve(net_dev))
>> +		return EFX_ENCAP_TYPE_GENEVE;
> netif_is_gretap or NVGRE isn't supported?

It should be supported, the hardware can handle it.
I'll add it in v2, and test to make sure it actually works ;)

>> +static const char *efx_tc_encap_type_name(enum efx_encap_type typ, char *buf,
>> +					  size_t n)
>> +{
>> +	switch (typ) {
>> +	case EFX_ENCAP_TYPE_NONE:
>> +		return "none";
>> +	case EFX_ENCAP_TYPE_VXLAN:
>> +		return "vxlan";
>> +	case EFX_ENCAP_TYPE_NVGRE:
>> +		return "nvgre";
>> +	case EFX_ENCAP_TYPE_GENEVE:
>> +		return "geneve";
>> +	default:
>> +		snprintf(buf, n, "type %u\n", typ);
>> +		return buf;
> I will return unsupported here, instead of playing with buffer.

Hmm, maybe if I add a one-time netif_warn()?  I don't like the
 idea of not getting the bogus value out anywhere where it can
 be debugged.

>>  /* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */
> Is it a device documentation? Where it can be find?

Ahh, turns out this document isn't public :(  I'll see if we
 can get this section of it split out into something public.

> 
>>  enum efx_tc_action_order {
>> +	EFX_TC_AO_DECAP,
>>  	EFX_TC_AO_VLAN_POP,
>>  	EFX_TC_AO_VLAN_PUSH,
>>  	EFX_TC_AO_COUNT,
>> @@ -513,6 +558,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
>>  					  enum efx_tc_action_order new)
>>  {
>>  	switch (new) {
>> +	case EFX_TC_AO_DECAP:
>> +		if (act->decap)
>> +			return false;
>> +		fallthrough;
>>  	case EFX_TC_AO_VLAN_POP:
>>  		if (act->vlan_pop >= 2)
>>  			return false;
>> @@ -540,6 +589,288 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
>>  	}
>>  }
>>  
>> +static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
>> +					 struct net_device *net_dev,
>> +					 struct flow_cls_offload *tc)
>> +{
>> +	struct flow_rule *fr = flow_cls_offload_flow_rule(tc);
>> +	struct netlink_ext_ack *extack = tc->common.extack;
>> +	struct efx_tc_flow_rule *rule = NULL, *old = NULL;
>> +	struct efx_tc_action_set *act = NULL;
>> +	bool found = false, uplinked = false;
>> +	const struct flow_action_entry *fa;
>> +	struct efx_tc_match match;
>> +	struct efx_rep *to_efv;
>> +	s64 rc;
>> +	int i;
>> +
>> +	/* Parse match */
>> +	memset(&match, 0, sizeof(match));
>> +	rc = efx_tc_flower_parse_match(efx, fr, &match, NULL);
>> +	if (rc)
>> +		return rc;
>> +	/* The rule as given to us doesn't specify a source netdevice.
>> +	 * But, determining whether packets from a VF should match it is
>> +	 * complicated, so leave those to the software slowpath: qualify
>> +	 * the filter with source m-port == wire.
>> +	 */
>> +	rc = efx_tc_flower_external_mport(efx, EFX_EFV_PF);
> Let's define extern_port as s64, a rc as int, it will be more readable I
> think.

Will it?  I feel it looks more natural this way — this is the way
 it would be written if mports always fitted into an int; the fact
 that they're actually u32 and thus the value needs to be wider to
 hold either an mport or an -errno is locally irrelevant to the
 reader.

>> +	/* Parse actions.  For foreign rules we only support decap & redirect */
>> +	flow_action_for_each(i, fa, &fr->action) {
>> +		struct efx_tc_action_set save;
>> +
>> +		switch (fa->id) {
>> +		case FLOW_ACTION_REDIRECT:
>> +		case FLOW_ACTION_MIRRED:
>> +			/* See corresponding code in efx_tc_flower_replace() for
>> +			 * long explanations of what's going on here.
>> +			 */
>> +			save = *act;
> Why save is needed here? In one bloick You are changing act, in other
> save.

Below, we set:

>> +			act->dest_mport = rc;
>> +			act->deliver = 1;

but then if this action is a mirred egress mirror, we don't want the
 next action-set in the action-set-list to deliver to the same place.
So we save the action state (collection of mutations applied to the
 packet) before the mirred, so that we can resume from where we left
 off:

>> +			/* Mirror, so continue on with saved act */
>> +			save.count = NULL;
>> +			act = kzalloc(sizeof(*act), GFP_USER);
>> +			if (!act) {
>> +				rc = -ENOMEM;
>> +				goto release;
>> +			}
>> +			*act = save;

The setting of save.count is a copy-paste error; that's needed in
 the non-tunnel case (efx_tc_flower_replace()) since that has a
 separate block for attaching counters (handling the case of
 FLOW_ACTION_DROP which we don't accept here in
 efx_tc_flower_replace_foreign()), but it's not needed here; maybe
 that was part of the confusion.

>> +			rc = efx_mae_alloc_action_set(efx, act);
>> +			if (rc) {
>> +				NL_SET_ERR_MSG_MOD(extack,
>> +						   "Failed to write action set to hw (mirred)");
>> +				goto release;
>> +			}
>> +			list_add_tail(&act->list, &rule->acts.list);
>> +			act = NULL;
> act was allocated, You need to free it, or maybe it is being cleared in
> alloc_action_set()? However, this function is really hard to follow.
> Please explain it more widely.

The list_add_tail attaches act (the action-set) to the list in
 rule->acts (the action-set-list), meaning it will be freed when the
 action-set-list is destroyed by efx_tc_free_action_set_list(),
 either in this function's failure ladder or in efx_tc_delete_rule().
I will try and write an extended comment under /* Parse actions */ to
 explain the use of this act 'cursor'.  Or rather, I'll add the
 comment to the efx_tc_flower_replace() equivalent, which works the
 same way, and reference it from here.

>> +	rc = efx_mae_insert_rule(efx, &rule->match, EFX_TC_PRIO_TC,
>> +				 rule->acts.fw_id, &rule->fw_id);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw");
>> +		goto release_act;
>> +	}
> act is saved somewhere?

Sorry, this should be called `release_acts`, as its job is to
 remove the action-set-list (rule->acts) from hardware.  Will fix.

Thanks for the very thorough review of this series :)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ