Message ID | 1486125945-8641-1-git-send-email-bala.manoharan@linaro.org |
---|---|
State | Accepted |
Commit | aa3bbe4da1639ac4649c7d34ae75b0230ade70b2 |
Headers | show |
Series | [PATCHv3,1/2] linux-generic: classification: implement ipv6 packet matching rule | expand |
For this series: Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org> On Fri, Feb 3, 2017 at 6:45 AM, Balasubramanian Manoharan <bala.manoharan@linaro.org> wrote: > Adds test case for ipv6 source and destination address matching > > Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org> > --- > v3: performance enhancement using bitwise AND for ip address mask > > .../include/odp_classification_datamodel.h | 11 ++++- > .../include/odp_classification_inlines.h | 52 ++++++++++++++++++---- > .../linux-generic/include/odp_packet_internal.h | 5 +++ > platform/linux-generic/include/protocols/ip.h | 14 +++++- > platform/linux-generic/odp_classification.c | 27 +++++++++++ > platform/linux-generic/odp_packet.c | 2 +- > 6 files changed, 99 insertions(+), 12 deletions(-) > > diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h > index f6393ee..140f39e 100644 > --- a/platform/linux-generic/include/odp_classification_datamodel.h > +++ b/platform/linux-generic/include/odp_classification_datamodel.h > @@ -25,6 +25,7 @@ extern "C" { > #include <odp_packet_internal.h> > #include <odp_packet_io_internal.h> > #include <odp_queue_internal.h> > +#include <protocols/ip.h> > > /* Maximum Class Of Service Entry */ > #define ODP_COS_MAX_ENTRY 64 > @@ -43,7 +44,7 @@ extern "C" { > /* Max L3 QoS Value */ > #define ODP_COS_MAX_L3_QOS (1 << ODP_COS_L3_QOS_BITS) > /* Max PMR Term bits */ > -#define ODP_PMR_TERM_BYTES_MAX 8 > +#define ODP_PMR_TERM_BYTES_MAX 16 > > /** > Packet Matching Rule Term Value > @@ -67,6 +68,14 @@ typedef struct pmr_term_value { > /** End value of the range */ > uint64_t val_end; > } range; > + struct { > + _odp_ipv6_addr_t addr; > + _odp_ipv6_addr_t mask; > + } match_ipv6; > + struct { > + _odp_ipv6_addr_t addr_start; > + _odp_ipv6_addr_t addr_end; > + } range_ipv6; > }; > uint32_t offset; /**< Offset if term == ODP_PMR_CUSTOM_FRAME */ > uint32_t val_sz; /**< Size of the value to be matched */ > diff --git a/platform/linux-generic/include/odp_classification_inlines.h b/platform/linux-generic/include/odp_classification_inlines.h > index b839197..e6f9be9 100644 > --- a/platform/linux-generic/include/odp_classification_inlines.h > +++ b/platform/linux-generic/include/odp_classification_inlines.h > @@ -25,6 +25,8 @@ extern "C" { > #include <protocols/udp.h> > #include <protocols/tcp.h> > #include <odp_packet_internal.h> > +#include <stdio.h> > +#include <inttypes.h> > > /* PMR term value verification function > These functions verify the given PMR term value with the value in the packet > @@ -179,19 +181,53 @@ static inline int verify_pmr_dmac(const uint8_t *pkt_addr, > return 0; > } > > -static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED, > - odp_packet_hdr_t *pkt_hdr ODP_UNUSED, > - pmr_term_value_t *term_value ODP_UNUSED) > +static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr, > + odp_packet_hdr_t *pkt_hdr, > + pmr_term_value_t *term_value) > { > - ODP_UNIMPLEMENTED(); > + const _odp_ipv6hdr_t *ipv6; > + uint64_t addr[2]; > + > + if (!packet_hdr_has_ipv6(pkt_hdr)) > + return 0; > + > + ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset); > + > + addr[0] = ipv6->src_addr.u64[0]; > + addr[1] = ipv6->src_addr.u64[1]; > + > + /* 128 bit address is processed as two 64 bit value > + * for bitwise AND operation */ > + addr[0] = addr[0] & term_value->match_ipv6.mask.u64[0]; > + addr[1] = addr[1] & term_value->match_ipv6.mask.u64[1]; > + > + if (!memcmp(addr, term_value->match_ipv6.addr.u8, _ODP_IPV6ADDR_LEN)) > + return 1; > + > return 0; > } > > -static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED, > - odp_packet_hdr_t *pkt_hdr ODP_UNUSED, > - pmr_term_value_t *term_value ODP_UNUSED) > +static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr, > + odp_packet_hdr_t *pkt_hdr, > + pmr_term_value_t *term_value) > { > - ODP_UNIMPLEMENTED(); > + const _odp_ipv6hdr_t *ipv6; > + uint64_t addr[2]; > + > + if (!packet_hdr_has_ipv6(pkt_hdr)) > + return 0; > + ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset); > + addr[0] = ipv6->dst_addr.u64[0]; > + addr[1] = ipv6->dst_addr.u64[1]; > + > + /* 128 bit address is processed as two 64 bit value > + * for bitwise AND operation */ > + addr[0] = addr[0] & term_value->match_ipv6.mask.u64[0]; > + addr[1] = addr[1] & term_value->match_ipv6.mask.u64[1]; > + > + if (!memcmp(addr, term_value->match_ipv6.addr.u8, _ODP_IPV6ADDR_LEN)) > + return 1; > + > return 0; > } > > diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h > index e6e9d74..e3ada5c 100644 > --- a/platform/linux-generic/include/odp_packet_internal.h > +++ b/platform/linux-generic/include/odp_packet_internal.h > @@ -294,6 +294,11 @@ static inline int packet_hdr_has_eth(odp_packet_hdr_t *pkt_hdr) > return pkt_hdr->p.input_flags.eth; > } > > +static inline int packet_hdr_has_ipv6(odp_packet_hdr_t *pkt_hdr) > +{ > + return pkt_hdr->p.input_flags.ipv6; > +} > + > static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) > { > if (ts != NULL) { > diff --git a/platform/linux-generic/include/protocols/ip.h b/platform/linux-generic/include/protocols/ip.h > index 6c089e3..20041f1 100644 > --- a/platform/linux-generic/include/protocols/ip.h > +++ b/platform/linux-generic/include/protocols/ip.h > @@ -117,6 +117,16 @@ ODP_STATIC_ASSERT(sizeof(_odp_ipv4hdr_t) == _ODP_IPV4HDR_LEN, > (uint8_t)((((ver_tc_flow) & 0x0fc00000) >> 22) & 0xff) > > /** > + * Ipv6 address > + */ > +typedef union ODP_PACKED { > + uint8_t u8[16]; > + odp_u16be_t u16[8]; > + odp_u32be_t u32[4]; > + odp_u64be_t u64[2]; > +} _odp_ipv6_addr_t; > + > +/** > * IPv6 header > */ > typedef struct ODP_PACKED { > @@ -124,8 +134,8 @@ typedef struct ODP_PACKED { > odp_u16be_t payload_len; /**< Payload length */ > uint8_t next_hdr; /**< Next header */ > uint8_t hop_limit; /**< Hop limit */ > - uint8_t src_addr[16]; /**< Source address */ > - uint8_t dst_addr[16]; /**< Destination address */ > + _odp_ipv6_addr_t src_addr; /**< Source address */ > + _odp_ipv6_addr_t dst_addr; /**< Destination address */ > } _odp_ipv6hdr_t; > > /** @internal Compile time assert */ > diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c > index 50a7e54..4882c5c 100644 > --- a/platform/linux-generic/odp_classification.c > +++ b/platform/linux-generic/odp_classification.c > @@ -447,6 +447,32 @@ static int odp_pmr_create_term(pmr_term_value_t *value, > { > value->term = param->term; > value->range_term = param->range_term; > + uint8_t i; > + > + switch (value->term) { > + case ODP_PMR_SIP6_ADDR: > + case ODP_PMR_DIP6_ADDR: > + if (!value->range_term) { > + memset(value->match_ipv6.addr.u8, 0, 16); > + memset(value->match_ipv6.mask.u8, 0, 16); > + memcpy(&value->match_ipv6.addr.u8, param->match.value, > + param->val_sz); > + memcpy(&value->match_ipv6.mask.u8, param->match.mask, > + param->val_sz); > + for (i = 0; i < 2; i++) > + value->match_ipv6.addr.u64[i] &= > + value->match_ipv6.mask.u64[i]; > + } else { > + memset(value->range_ipv6.addr_start.u8, 0, 16); > + memset(value->range_ipv6.addr_end.u8, 0, 16); > + memcpy(&value->range_ipv6.addr_start.u8, param->range.val_start, > + param->val_sz); > + memcpy(&value->range_ipv6.addr_end.u8, param->range.val_end, > + param->val_sz); > + } > + > + break; > + default: > if (!value->range_term) { > value->match.value = 0; > value->match.mask = 0; > @@ -461,6 +487,7 @@ static int odp_pmr_create_term(pmr_term_value_t *value, > memcpy(&value->range.val_end, param->range.val_end, > param->val_sz); > } > + } > value->offset = param->offset; > value->val_sz = param->val_sz; > return 0; > diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c > index 34d720c..a87b2d9 100644 > --- a/platform/linux-generic/odp_packet.c > +++ b/platform/linux-generic/odp_packet.c > @@ -1888,7 +1888,7 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, > { > const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; > const _odp_ipv6hdr_ext_t *ipv6ext; > - uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr[0]); > + uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); > > prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) + > _ODP_IPV6HDR_LEN; > -- > 1.9.1 >
diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h index f6393ee..140f39e 100644 --- a/platform/linux-generic/include/odp_classification_datamodel.h +++ b/platform/linux-generic/include/odp_classification_datamodel.h @@ -25,6 +25,7 @@ extern "C" { #include <odp_packet_internal.h> #include <odp_packet_io_internal.h> #include <odp_queue_internal.h> +#include <protocols/ip.h> /* Maximum Class Of Service Entry */ #define ODP_COS_MAX_ENTRY 64 @@ -43,7 +44,7 @@ extern "C" { /* Max L3 QoS Value */ #define ODP_COS_MAX_L3_QOS (1 << ODP_COS_L3_QOS_BITS) /* Max PMR Term bits */ -#define ODP_PMR_TERM_BYTES_MAX 8 +#define ODP_PMR_TERM_BYTES_MAX 16 /** Packet Matching Rule Term Value @@ -67,6 +68,14 @@ typedef struct pmr_term_value { /** End value of the range */ uint64_t val_end; } range; + struct { + _odp_ipv6_addr_t addr; + _odp_ipv6_addr_t mask; + } match_ipv6; + struct { + _odp_ipv6_addr_t addr_start; + _odp_ipv6_addr_t addr_end; + } range_ipv6; }; uint32_t offset; /**< Offset if term == ODP_PMR_CUSTOM_FRAME */ uint32_t val_sz; /**< Size of the value to be matched */ diff --git a/platform/linux-generic/include/odp_classification_inlines.h b/platform/linux-generic/include/odp_classification_inlines.h index b839197..e6f9be9 100644 --- a/platform/linux-generic/include/odp_classification_inlines.h +++ b/platform/linux-generic/include/odp_classification_inlines.h @@ -25,6 +25,8 @@ extern "C" { #include <protocols/udp.h> #include <protocols/tcp.h> #include <odp_packet_internal.h> +#include <stdio.h> +#include <inttypes.h> /* PMR term value verification function These functions verify the given PMR term value with the value in the packet @@ -179,19 +181,53 @@ static inline int verify_pmr_dmac(const uint8_t *pkt_addr, return 0; } -static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED, - odp_packet_hdr_t *pkt_hdr ODP_UNUSED, - pmr_term_value_t *term_value ODP_UNUSED) +static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr, + odp_packet_hdr_t *pkt_hdr, + pmr_term_value_t *term_value) { - ODP_UNIMPLEMENTED(); + const _odp_ipv6hdr_t *ipv6; + uint64_t addr[2]; + + if (!packet_hdr_has_ipv6(pkt_hdr)) + return 0; + + ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset); + + addr[0] = ipv6->src_addr.u64[0]; + addr[1] = ipv6->src_addr.u64[1]; + + /* 128 bit address is processed as two 64 bit value + * for bitwise AND operation */ + addr[0] = addr[0] & term_value->match_ipv6.mask.u64[0]; + addr[1] = addr[1] & term_value->match_ipv6.mask.u64[1]; + + if (!memcmp(addr, term_value->match_ipv6.addr.u8, _ODP_IPV6ADDR_LEN)) + return 1; + return 0; } -static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED, - odp_packet_hdr_t *pkt_hdr ODP_UNUSED, - pmr_term_value_t *term_value ODP_UNUSED) +static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr, + odp_packet_hdr_t *pkt_hdr, + pmr_term_value_t *term_value) { - ODP_UNIMPLEMENTED(); + const _odp_ipv6hdr_t *ipv6; + uint64_t addr[2]; + + if (!packet_hdr_has_ipv6(pkt_hdr)) + return 0; + ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset); + addr[0] = ipv6->dst_addr.u64[0]; + addr[1] = ipv6->dst_addr.u64[1]; + + /* 128 bit address is processed as two 64 bit value + * for bitwise AND operation */ + addr[0] = addr[0] & term_value->match_ipv6.mask.u64[0]; + addr[1] = addr[1] & term_value->match_ipv6.mask.u64[1]; + + if (!memcmp(addr, term_value->match_ipv6.addr.u8, _ODP_IPV6ADDR_LEN)) + return 1; + return 0; } diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index e6e9d74..e3ada5c 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -294,6 +294,11 @@ static inline int packet_hdr_has_eth(odp_packet_hdr_t *pkt_hdr) return pkt_hdr->p.input_flags.eth; } +static inline int packet_hdr_has_ipv6(odp_packet_hdr_t *pkt_hdr) +{ + return pkt_hdr->p.input_flags.ipv6; +} + static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) { if (ts != NULL) { diff --git a/platform/linux-generic/include/protocols/ip.h b/platform/linux-generic/include/protocols/ip.h index 6c089e3..20041f1 100644 --- a/platform/linux-generic/include/protocols/ip.h +++ b/platform/linux-generic/include/protocols/ip.h @@ -117,6 +117,16 @@ ODP_STATIC_ASSERT(sizeof(_odp_ipv4hdr_t) == _ODP_IPV4HDR_LEN, (uint8_t)((((ver_tc_flow) & 0x0fc00000) >> 22) & 0xff) /** + * Ipv6 address + */ +typedef union ODP_PACKED { + uint8_t u8[16]; + odp_u16be_t u16[8]; + odp_u32be_t u32[4]; + odp_u64be_t u64[2]; +} _odp_ipv6_addr_t; + +/** * IPv6 header */ typedef struct ODP_PACKED { @@ -124,8 +134,8 @@ typedef struct ODP_PACKED { odp_u16be_t payload_len; /**< Payload length */ uint8_t next_hdr; /**< Next header */ uint8_t hop_limit; /**< Hop limit */ - uint8_t src_addr[16]; /**< Source address */ - uint8_t dst_addr[16]; /**< Destination address */ + _odp_ipv6_addr_t src_addr; /**< Source address */ + _odp_ipv6_addr_t dst_addr; /**< Destination address */ } _odp_ipv6hdr_t; /** @internal Compile time assert */ diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index 50a7e54..4882c5c 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -447,6 +447,32 @@ static int odp_pmr_create_term(pmr_term_value_t *value, { value->term = param->term; value->range_term = param->range_term; + uint8_t i; + + switch (value->term) { + case ODP_PMR_SIP6_ADDR: + case ODP_PMR_DIP6_ADDR: + if (!value->range_term) { + memset(value->match_ipv6.addr.u8, 0, 16); + memset(value->match_ipv6.mask.u8, 0, 16); + memcpy(&value->match_ipv6.addr.u8, param->match.value, + param->val_sz); + memcpy(&value->match_ipv6.mask.u8, param->match.mask, + param->val_sz); + for (i = 0; i < 2; i++) + value->match_ipv6.addr.u64[i] &= + value->match_ipv6.mask.u64[i]; + } else { + memset(value->range_ipv6.addr_start.u8, 0, 16); + memset(value->range_ipv6.addr_end.u8, 0, 16); + memcpy(&value->range_ipv6.addr_start.u8, param->range.val_start, + param->val_sz); + memcpy(&value->range_ipv6.addr_end.u8, param->range.val_end, + param->val_sz); + } + + break; + default: if (!value->range_term) { value->match.value = 0; value->match.mask = 0; @@ -461,6 +487,7 @@ static int odp_pmr_create_term(pmr_term_value_t *value, memcpy(&value->range.val_end, param->range.val_end, param->val_sz); } + } value->offset = param->offset; value->val_sz = param->val_sz; return 0; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 34d720c..a87b2d9 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -1888,7 +1888,7 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, { const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; const _odp_ipv6hdr_ext_t *ipv6ext; - uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr[0]); + uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) + _ODP_IPV6HDR_LEN;
Adds test case for ipv6 source and destination address matching Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org> --- v3: performance enhancement using bitwise AND for ip address mask .../include/odp_classification_datamodel.h | 11 ++++- .../include/odp_classification_inlines.h | 52 ++++++++++++++++++---- .../linux-generic/include/odp_packet_internal.h | 5 +++ platform/linux-generic/include/protocols/ip.h | 14 +++++- platform/linux-generic/odp_classification.c | 27 +++++++++++ platform/linux-generic/odp_packet.c | 2 +- 6 files changed, 99 insertions(+), 12 deletions(-) -- 1.9.1