net/softnic: support flow API VXLAN encap action
Added support for ethdev flow API VXLAN encap action. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
0dac5d7ea0
commit
636e5af038
@ -1634,6 +1634,198 @@ flow_rule_action_get(struct pmd_internals *softnic,
|
|||||||
break;
|
break;
|
||||||
} /* RTE_FLOW_ACTION_TYPE_METER */
|
} /* RTE_FLOW_ACTION_TYPE_METER */
|
||||||
|
|
||||||
|
case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
|
||||||
|
{
|
||||||
|
const struct rte_flow_action_vxlan_encap *conf =
|
||||||
|
action->conf;
|
||||||
|
const struct rte_flow_item *item;
|
||||||
|
union flow_item spec, mask;
|
||||||
|
int disabled = 0, status;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (conf == NULL)
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||||
|
action,
|
||||||
|
"VXLAN ENCAP: Null configuration");
|
||||||
|
|
||||||
|
item = conf->definition;
|
||||||
|
if (item == NULL)
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ACTION,
|
||||||
|
action,
|
||||||
|
"VXLAN ENCAP: Null configuration definition");
|
||||||
|
|
||||||
|
if (!(params->action_mask &
|
||||||
|
(1LLU << RTE_TABLE_ACTION_ENCAP)))
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
|
||||||
|
NULL,
|
||||||
|
"VXLAN ENCAP: Encap action not enabled for this table");
|
||||||
|
|
||||||
|
/* Check for Ether. */
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
status = flow_item_proto_preprocess(item, &spec, &mask,
|
||||||
|
&size, &disabled, error);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: first encap item should be ether");
|
||||||
|
}
|
||||||
|
ether_addr_copy(&spec.eth.dst,
|
||||||
|
&rule_action->encap.vxlan.ether.da);
|
||||||
|
ether_addr_copy(&spec.eth.src,
|
||||||
|
&rule_action->encap.vxlan.ether.sa);
|
||||||
|
|
||||||
|
item++;
|
||||||
|
|
||||||
|
/* Check for VLAN. */
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
status = flow_item_proto_preprocess(item, &spec, &mask,
|
||||||
|
&size, &disabled, error);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
|
||||||
|
if (!params->encap.vxlan.vlan)
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
ENOTSUP,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: vlan encap not supported by table");
|
||||||
|
|
||||||
|
uint16_t tci = rte_ntohs(spec.vlan.tci);
|
||||||
|
rule_action->encap.vxlan.vlan.pcp =
|
||||||
|
tci >> 13;
|
||||||
|
rule_action->encap.vxlan.vlan.dei =
|
||||||
|
(tci >> 12) & 0x1;
|
||||||
|
rule_action->encap.vxlan.vlan.vid =
|
||||||
|
tci & 0xfff;
|
||||||
|
|
||||||
|
item++;
|
||||||
|
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
status = flow_item_proto_preprocess(item, &spec,
|
||||||
|
&mask, &size, &disabled, error);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
if (params->encap.vxlan.vlan)
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
ENOTSUP,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: expecting vlan encap item");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for IPV4/IPV6. */
|
||||||
|
switch (item->type) {
|
||||||
|
case RTE_FLOW_ITEM_TYPE_IPV4:
|
||||||
|
{
|
||||||
|
rule_action->encap.vxlan.ipv4.sa =
|
||||||
|
rte_ntohl(spec.ipv4.hdr.src_addr);
|
||||||
|
rule_action->encap.vxlan.ipv4.da =
|
||||||
|
rte_ntohl(spec.ipv4.hdr.dst_addr);
|
||||||
|
rule_action->encap.vxlan.ipv4.dscp =
|
||||||
|
spec.ipv4.hdr.type_of_service >> 2;
|
||||||
|
rule_action->encap.vxlan.ipv4.ttl =
|
||||||
|
spec.ipv4.hdr.time_to_live;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RTE_FLOW_ITEM_TYPE_IPV6:
|
||||||
|
{
|
||||||
|
uint32_t vtc_flow;
|
||||||
|
|
||||||
|
memcpy(&rule_action->encap.vxlan.ipv6.sa,
|
||||||
|
&spec.ipv6.hdr.src_addr,
|
||||||
|
sizeof(spec.ipv6.hdr.src_addr));
|
||||||
|
memcpy(&rule_action->encap.vxlan.ipv6.da,
|
||||||
|
&spec.ipv6.hdr.dst_addr,
|
||||||
|
sizeof(spec.ipv6.hdr.dst_addr));
|
||||||
|
vtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);
|
||||||
|
rule_action->encap.vxlan.ipv6.flow_label =
|
||||||
|
vtc_flow & 0xfffff;
|
||||||
|
rule_action->encap.vxlan.ipv6.dscp =
|
||||||
|
(vtc_flow >> 22) & 0x3f;
|
||||||
|
rule_action->encap.vxlan.ipv6.hop_limit =
|
||||||
|
spec.ipv6.hdr.hop_limits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: encap item after ether should be ipv4/ipv6");
|
||||||
|
}
|
||||||
|
|
||||||
|
item++;
|
||||||
|
|
||||||
|
/* Check for UDP. */
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
status = flow_item_proto_preprocess(item, &spec, &mask,
|
||||||
|
&size, &disabled, error);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (item->type != RTE_FLOW_ITEM_TYPE_UDP) {
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp");
|
||||||
|
}
|
||||||
|
rule_action->encap.vxlan.udp.sp =
|
||||||
|
rte_ntohs(spec.udp.hdr.src_port);
|
||||||
|
rule_action->encap.vxlan.udp.dp =
|
||||||
|
rte_ntohs(spec.udp.hdr.dst_port);
|
||||||
|
|
||||||
|
item++;
|
||||||
|
|
||||||
|
/* Check for VXLAN. */
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
status = flow_item_proto_preprocess(item, &spec, &mask,
|
||||||
|
&size, &disabled, error);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: encap item after udp should be vxlan");
|
||||||
|
}
|
||||||
|
rule_action->encap.vxlan.vxlan.vni =
|
||||||
|
(spec.vxlan.vni[0] << 16U |
|
||||||
|
spec.vxlan.vni[1] << 8U
|
||||||
|
| spec.vxlan.vni[2]);
|
||||||
|
|
||||||
|
item++;
|
||||||
|
|
||||||
|
/* Check for END. */
|
||||||
|
flow_item_skip_void(&item);
|
||||||
|
|
||||||
|
if (item->type != RTE_FLOW_ITEM_TYPE_END)
|
||||||
|
return rte_flow_error_set(error,
|
||||||
|
EINVAL,
|
||||||
|
RTE_FLOW_ERROR_TYPE_ITEM,
|
||||||
|
item,
|
||||||
|
"VXLAN ENCAP: expecting END item");
|
||||||
|
|
||||||
|
rule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
|
||||||
|
rule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
|
||||||
|
break;
|
||||||
|
} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user