Multiprotocol Label Switching
This new capability enables the user to match MPLS tunnel over UDP when in HW steering mode. It supports multiple MPLS headers for matching as well as encapsulation/decapsulation. The maximum supported MPLS headers is 5.
# Create a template table with 3
MPLS headers.
flow pattern_template 0
create pattern_template_id 1
ingress template eth / ipv4 / udp / mpls / mpls / mpls label mask 0xfffff
s mask 1
/ ipv4 / end
flow actions_template 0
create actions_template_id 1
template queue / end mask queue / end
flow template_table 0
create table_id 1
group 1
priority 0
ingress rules_number 64
pattern_template 1
actions_template 1
# Create a flow match packets with exactly 3
MPLS headers.
flow queue 0
create 0
template_table 1
pattern_template 0
actions_template 0
postpone no pattern eth / ipv4 / udp / mpls / mpls / mpls label is 0xabcde
s is 1
/ ipv4 / end actions queue index 1
/ end
# Create a flow match packets with more than 3
MPLS headers.
flow queue 0
create 0
template_table 1
pattern_template 0
actions_template 0
postpone no pattern eth / ipv4 / udp / mpls / mpls / mpls label is 0x12345
s is 0
/ ipv4 / end actions queue index 1
/ end
struct rte_flow_pattern_template *
create_pattern_template(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_item_mpls mpls_item = {
.label_tc_s = "\xff\xff\xf1"
,
};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.type = RTE_FLOW_ITEM_TYPE_IPV4,
},
{
.type = RTE_FLOW_ITEM_TYPE_UDP,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
.mask = &mpls_item,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
const
struct rte_flow_pattern_template_attr pt_attr = {
.relaxed_matching = 0
,
.ingress = 1
,
};
return
rte_flow_pattern_template_create(port_id, &pt_attr, pattern, &error);
}
struct rte_flow_actions_template *
create_actions_template(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_action_queue queue_v = {
.index = 0
};
struct rte_flow_action_queue queue_m = {
.index = UINT16_MAX
};
struct rte_flow_action actions[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_v,
},
{
.type = RTE_FLOW_ACTION_TYPE_END,
},
};
struct rte_flow_action masks[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_m,
},
{
.type = RTE_FLOW_ACTION_TYPE_END,
},
};
const
struct rte_flow_actions_template_attr at_attr = {
.ingress = 1
,
};
return
rte_flow_actions_template_create(port_id, &at_attr, actions, masks, error);
}
struct rte_flow_template_table *
create_table(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_pattern_template *pt;
struct rte_flow_actions_template *at;
const
struct rte_flow_template_table_attr tbl_attr = {
.flow_attr = {
.group = 1
,
.priority = 0
,
.ingress = 1
,
},
.nb_flows = 1000
,
};
pt = create_pattern_template(port_id, error);
if
(pt == NULL) {
printf("Failed to create pattern template: %s (%s) \n"
,
error.message, rte_strerror(rte_errno));
return
NULL;
}
at = create_actions_template(port_id, error);
if
(at[0
] == NULL) {
printf("Failed to create actions template: %s (%s)\n"
,
error.message, rte_strerror(rte_errno));
return
NULL;
}
return
rte_flow_template_table_create(port_id, &tbl_attr, &pt, 1
, &at, 1
, error);
}
void
create_mpls_rule(void
)
{
uint16_t port_id = PORT_ID;
uint32_t queue_id = QUEUE_ID;
struct rte_flow_error error = { 0
};
struct rte_flow_op_attr attr = {
.postpone = 0
,
};
struct rte_flow_item_mpls mpls_item = {
.label_tc_s = "\xab\xcd\xe1"
,
};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.type = RTE_FLOW_ITEM_TYPE_IPV4,
},
{
.type = RTE_FLOW_ITEM_TYPE_UDP,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
},
{
.type = RTE_FLOW_ITEM_TYPE_MPLS,
.spec = &mpls_item,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
struct rte_flow_action_queue queue = {
.index = UINT16_MAX
};
struct rte_flow_action actions[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue
},
{
.type = RTE_FLOW_ACTION_TYPE_END,
},
};
struct rte_flow_template_table *table;
struct rte_flow *flow;
table = create_table(port_id, &error);
if
(table == NULL) {
printf("Failed to create template table: %s (%s)\n"
,
error.message, rte_strerror(rte_errno));
rte_exit(EXIT_FAILURE, "Exiting"
);
}
flow = rte_flow_async_create(port_id, queue_id, &attr, table, pattern, 0
, actions, 1
, NULL, &error);
if
(flow == NULL) {
printf("Failed to enqueue flow create operation: %s (%s) \n"
,
error.message, rte_strerror(rte_errno));
rte_exit(EXIT_FAILURE, "Exiting"
);
};
}