Documente Academic
Documente Profesional
Documente Cultură
24.1. Overview
24.1.1. Rule denition
The current implementation allows the user for each AC context to specify its own rule (set of
elds) over which packet classication will be performed. Though there are few restrictions on
the rule elds layout:
First eld in the rule denition has to be one byte long.
All subsequent elds has to be grouped into sets of 4 consecutive bytes.
This is done mainly for performance reasons - search function processes the rst input byte as
part of the ow setup and then the inner loop of the search function is unrolled to process four
input bytes at a time.
To dene each eld inside an AC rule, the following structure is used:
structrte_acl_field_def{
uint8_ttype;/*<typeACL_FIELD_TYPE.*/
uint8_tsize;/*<sizeoffield1,2,4,or8.*/
uint8_tfield_index;/*<indexoffieldinsidetherule.*/
uint8_tinput_index;/*<0Ninputindex.*/
uint32_toffset;/*<offsettostartoffield.*/
};
structipv4_5tuple{
uint8_tproto;
uint32_tip_src;
uint32_tip_dst;
uint16_tport_src;
uint16_tport_dst;
};
structrte_acl_field_defipv4_defs[5]={
/*firstinputfieldalwaysonebytelong.*/
{
.type=RTE_ACL_FIELD_TYPE_BITMASK,
.size=sizeof(uint8_t),
.field_index=0,
.input_index=0,
.offset=offsetof(structipv4_5tuple,proto),
},
/*nextinputfield(IPv4sourceaddress)4consecutivebytes.*/
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=1,
.input_index=1,
.offset=offsetof(structipv4_5tuple,ip_src),
},
/*nextinputfield(IPv4destinationaddress)4consecutivebytes.*/
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=2,
.input_index=2,
.offset=offsetof(structipv4_5tuple,ip_dst),
},
/*
*Next2fields(src&dstports)form4consecutivebytes.
*Theysharethesameinputindex.
*/
{
.type=RTE_ACL_FIELD_TYPE_RANGE,
.size=sizeof(uint16_t),
.field_index=3,
.input_index=3,
.offset=offsetof(structipv4_5tuple,port_src),
},
{
.type=RTE_ACL_FIELD_TYPE_RANGE,
.size=sizeof(uint16_t),
.field_index=4,
.input_index=3,
.offset=offsetof(structipv4_5tuple,port_dst),
},
};
sourceaddr/maskdestinationaddr/masksourceportsdestportsprotocol/mask
192.168.1.0/24192.168.2.31/320:655351234:123417/0xff
Any IPv4 packets with protocol ID 17 (UDP), source address 192.168.1.[0-255], destination
address 192.168.2.31, source port [0-65535] and destination port 1234 matches the above rule.
To dene classication for the IPv6 2-tuple: <protocol, IPv6 source address> over the following
IPv6 header structure:
structstructipv6_hdr{
uint32_tvtc_flow;/*IPversion,trafficclass&flowlabel.*/
uint16_tpayload_len;/*IPpacketlengthincludessizeof(ip_header).*/
uint8_tproto;/*Protocol,nextheader.*/
uint8_thop_limits;/*Hoplimits.*/
uint8_tsrc_addr[16];/*IPaddressofsourcehost.*/
uint8_tdst_addr[16];/*IPaddressofdestinationhost(s).*/
}__attribute__((__packed__));
structstructrte_acl_field_defipv6_2tuple_defs[5]={
{
.type=RTE_ACL_FIELD_TYPE_BITMASK,
.size=sizeof(uint8_t),
.field_index=0,
.input_index=0,
.offset=offsetof(structipv6_hdr,proto),
},
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=1,
.input_index=1,
.offset=offsetof(structipv6_hdr,src_addr[0]),
},
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=2,
.input_index=2,
.offset=offsetof(structipv6_hdr,src_addr[4]),
},
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=3,
.input_index=3,
.offset=offsetof(structipv6_hdr,src_addr[8]),
},
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=4,
.input_index=4,
.offset=offsetof(structipv6_hdr,src_addr[12]),
},
};
sourceaddr/maskprotocol/mask
2001:db8:1234:0000:0000:0000:0000:0000/486/0xff
Any IPv6 packets with protocol ID 6 (TCP), and source address inside the range
[2001:db8:1234:0000:0000:0000:0000:0000 - 2001:db8:1234:ffff:ffff:ffff:ffff:ffff] matches the
above rule.
In the following example the last element of the search key is 8-bit long. So it is a case where the 4
consecutive bytes of an input eld are not fully occupied. The structure for the classication is:
structacl_key{
uint8_tip_proto;
uint32_tip_src;
uint32_tip_dst;
uint8_ttos;/*<Thisispartiallyusinga32bitinputelement*/
};
structrte_acl_field_defipv4_defs[4]={
/*firstinputfieldalwaysonebytelong.*/
{
.type=RTE_ACL_FIELD_TYPE_BITMASK,
.size=sizeof(uint8_t),
.field_index=0,
.input_index=0,
.offset=offsetof(structacl_key,ip_proto),
},
/*nextinputfield(IPv4sourceaddress)4consecutivebytes.*/
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=1,
.input_index=1,
.offset=offsetof(structacl_key,ip_src),
},
/*nextinputfield(IPv4destinationaddress)4consecutivebytes.*/
{
.type=RTE_ACL_FIELD_TYPE_MASK,
.size=sizeof(uint32_t),
.field_index=2,
.input_index=2,
.offset=offsetof(structacl_key,ip_dst),
},
/*
*Nextelementofsearchkey(TypeofService)isindeed1bytelong.
*Anywayweneedtoallocateallthe4consecutivebytesforit.
*/
{
.type=RTE_ACL_FIELD_TYPE_BITMASK,
.size=sizeof(uint32_t),/*Allthe4consecutivebytesareallocated*/
.field_index=3,
.input_index=3,
.offset=offsetof(structacl_key,tos),
},
};
sourceaddr/maskdestinationaddr/masktos/maskprotocol/mask
192.168.1.0/24192.168.2.31/321/0xff6/0xff
Any IPv4 packets with protocol ID 6 (TCP), source address 192.168.1.[0-255], destination
address 192.168.2.31, ToS 1 matches the above rule.
When creating a set of rules, for each rule, additional information must be supplied also:
priority: A weight to measure the priority of the rules (higher is better). If the input tuple
matches more than one rule, then the rule with the higher priority is returned. Note that if the
input tuple matches more than one rule and these rules have equal priority, it is undened
which rule is returned as a match. It is recommended to assign a unique priority for each rule.
category_mask: Each rule uses a bit mask value to select the relevant category(s) for the rule.
When a lookup is performed, the result for each category is returned. This effectively provides
a parallel lookup by enabling a single search to return multiple results if, for example, there
were four different sets of ACL rules, one for access control, one for routing, and so on. Each
set could be assigned its own category and by combining them into a single database, one
lookup returns a result for each of the four sets.
userdata: A user-dened eld that could be any value except zero. For each category, a
successful match returns the userdata eld of the highest priority matched rule.
Note
When adding new rules into an ACL context, all elds must be in host byte order (LSB). When
the search is performed for an input tuple, all elds in that tuple must be in network byte
order (MSB).
structrte_acl_ctx*acx;
structrte_acl_configcfg;
intret;
/*
*assumingthatacxpointstoalreadycreatedand
*populatedwithrulesACcontextandcfgfilledproperly.
*/
/*trytobuildACcontext,withRTstructureslessthen8MB.*/
cfg.max_size=0x800000;
ret=rte_acl_build(acx,&cfg);
/*
*RTstructurescan'tfitinto8MBforgivencontext.
*Trytobuildwithoutexposinganyhardlimit.
*/
if(ret==ERANGE){
cfg.max_size=0;
ret=rte_acl_build(acx,&cfg);
}
Note
For more details about the Access Control API, please refer to the DPDK API Reference.
The following example demonstrates IPv4, 5-tuple classication for rules dened above with
multiple categories in more detail.
structrte_acl_ctx*acx;
structrte_acl_configcfg;
intret;
/*defineastructurefortherulewithupto5fields.*/
RTE_ACL_RULE_DEF(acl_ipv4_rule,RTE_DIM(ipv4_defs));
/*ACcontextcreationparameters.*/
structrte_acl_paramprm={
.name="ACL_example",
.socket_id=SOCKET_ID_ANY,
.rule_size=RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs)),
/*numberoffieldsperrule.*/
.max_rule_num=8,/*maximumnumberofrulesintheACcontext.*/
};
structacl_ipv4_ruleacl_rules[]={
/*matchesallpacketstravelingto192.168.0.0/16,appliesforcategories:0,1*/
{
.data={.userdata=1,.category_mask=3,.priority=1},
/*destinationIPv4*/
.field[2]={.value.u32=IPv4(192,168,0,0),.mask_range.u32=16,},
/*sourceport*/
.field[3]={.value.u16=0,.mask_range.u16=0xffff,},
/*destinationport*/
.field[4]={.value.u16=0,.mask_range.u16=0xffff,},
},
/*matchesallpacketstravelingto192.168.1.0/24,appliesforcategories:0*/
{
.data={.userdata=2,.category_mask=1,.priority=2},
/*destinationIPv4*/
.field[2]={.value.u32=IPv4(192,168,1,0),.mask_range.u32=24,},
/*sourceport*/
.field[3]={.value.u16=0,.mask_range.u16=0xffff,},
/*destinationport*/
.field[4]={.value.u16=0,.mask_range.u16=0xffff,},
},
/*matchesallpacketstravelingfrom10.1.1.1,appliesforcategories:1*/
{
.data={.userdata=3,.category_mask=2,.priority=3},
/*sourceIPv4*/
.field[1]={.value.u32=IPv4(10,1,1,1),.mask_range.u32=32,},
/*sourceport*/
.field[3]={.value.u16=0,.mask_range.u16=0xffff,},
/*destinationport*/
.field[4]={.value.u16=0,.mask_range.u16=0xffff,},
},
};
/*createanemptyACcontext*/
if((acx=rte_acl_create(&prm))==NULL){
/*handlecontextcreatefailure.*/
}
/*addrulestothecontext*/
ret=rte_acl_add_rules(acx,acl_rules,RTE_DIM(acl_rules));
if(ret!=0){
/*handleerrorataddingACLrules.*/
}
/*prepareACbuildconfig.*/
cfg.num_categories=2;
cfg.num_fields=RTE_DIM(ipv4_defs);
memcpy(cfg.defs,ipv4_defs,sizeof(ipv4_defs));
/*buildtheruntimestructuresforaddedrules,with2categories.*/
ret=rte_acl_build(acx,&cfg);
if(ret!=0){
/*handleerroratbuildruntimestructuresforACLcontext.*/
}
For a tuple with source IP address: 10.1.1.1 and destination IP address: 192.168.1.15, once the
following lines are executed:
uint32_tresults[4];/*makeclassifyfor4categories.*/
rte_acl_classify(acx,data,results,1,4);
results[4]={2,3,0,0};
For category 0, both rules 1 and 2 match, but rule 2 has higher priority, therefore results[0]
contains the userdata for rule 2.
For category 1, both rules 1 and 3 match, but rule 3 has higher priority, therefore results[1]
contains the userdata for rule 3.
For categories 2 and 3, there are no matches, so results[2] and results[3] contain zero, which
indicates that no matches were found for those categories.
For a tuple with source IP address: 192.168.1.1 and destination IP address: 192.168.2.11, once
the following lines are executed:
uint32_tresults[4];/*makeclassifyby4categories.*/
rte_acl_classify(acx,data,results,1,4);
results[4]={1,1,0,0};
uint32_tresults[4];/*makeclassifyby4categories.*/
rte_acl_classify(acx,data,results,1,4);
results[4]={0,3,0,0};