From patchwork Fri Sep 7 15:58:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 44418 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 15CC3493D; Fri, 7 Sep 2018 17:59:25 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 633A83256 for ; Fri, 7 Sep 2018 17:59:22 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Sep 2018 08:59:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,343,1531810800"; d="scan'208";a="78757026" Received: from silpixa00382658.ir.intel.com ([10.237.223.29]) by FMSMGA003.fm.intel.com with ESMTP; 07 Sep 2018 08:59:03 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Date: Fri, 7 Sep 2018 16:58:50 +0100 Message-Id: <1536335931-171094-1-git-send-email-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [dpdk-dev] [PATCH 1/2] pipeline: add vxlan encap X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support for VXLAN as part of the encap table action. Signed-off-by: Cristian Dumitrescu --- lib/librte_pipeline/rte_table_action.c | 356 +++++++++++++++++++++++++++++++++ lib/librte_pipeline/rte_table_action.h | 75 +++++++ 2 files changed, 431 insertions(+) diff --git a/lib/librte_pipeline/rte_table_action.c b/lib/librte_pipeline/rte_table_action.c index 83ffa5d..338dcfe 100644 --- a/lib/librte_pipeline/rte_table_action.c +++ b/lib/librte_pipeline/rte_table_action.c @@ -430,6 +430,7 @@ encap_valid(enum rte_table_action_encap_type encap) case RTE_TABLE_ACTION_ENCAP_QINQ: case RTE_TABLE_ACTION_ENCAP_MPLS: case RTE_TABLE_ACTION_ENCAP_PPPOE: + case RTE_TABLE_ACTION_ENCAP_VXLAN: return 1; default: return 0; @@ -498,6 +499,38 @@ struct encap_pppoe_data { struct pppoe_ppp_hdr pppoe_ppp; } __attribute__((__packed__)); +#define IP_PROTO_UDP 17 + +struct encap_vxlan_ipv4_data { + struct ether_hdr ether; + struct ipv4_hdr ipv4; + struct udp_hdr udp; + struct vxlan_hdr vxlan; +} __attribute__((__packed__)); + +struct encap_vxlan_ipv4_vlan_data { + struct ether_hdr ether; + struct vlan_hdr vlan; + struct ipv4_hdr ipv4; + struct udp_hdr udp; + struct vxlan_hdr vxlan; +} __attribute__((__packed__)); + +struct encap_vxlan_ipv6_data { + struct ether_hdr ether; + struct ipv6_hdr ipv6; + struct udp_hdr udp; + struct vxlan_hdr vxlan; +} __attribute__((__packed__)); + +struct encap_vxlan_ipv6_vlan_data { + struct ether_hdr ether; + struct vlan_hdr vlan; + struct ipv6_hdr ipv6; + struct udp_hdr udp; + struct vxlan_hdr vxlan; +} __attribute__((__packed__)); + static size_t encap_data_size(struct rte_table_action_encap_config *encap) { @@ -517,6 +550,18 @@ encap_data_size(struct rte_table_action_encap_config *encap) case 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE: return sizeof(struct encap_pppoe_data); + case 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN: + if (encap->vxlan.ip_version) + if (encap->vxlan.vlan) + return sizeof(struct encap_vxlan_ipv4_vlan_data); + else + return sizeof(struct encap_vxlan_ipv4_data); + else + if (encap->vxlan.vlan) + return sizeof(struct encap_vxlan_ipv6_vlan_data); + else + return sizeof(struct encap_vxlan_ipv6_data); + default: return 0; } @@ -550,6 +595,9 @@ encap_apply_check(struct rte_table_action_encap_params *p, case RTE_TABLE_ACTION_ENCAP_PPPOE: return 0; + case RTE_TABLE_ACTION_ENCAP_VXLAN: + return 0; + default: return -EINVAL; } @@ -679,6 +727,168 @@ encap_pppoe_apply(void *data, } static int +encap_vxlan_apply(void *data, + struct rte_table_action_encap_params *p, + struct rte_table_action_encap_config *cfg) +{ + if ((p->vxlan.vxlan.vni > 0xFFFFFF) || + (cfg->vxlan.ip_version && (p->vxlan.ipv4.dscp > 0x3F)) || + (!cfg->vxlan.ip_version && (p->vxlan.ipv6.flow_label > 0xFFFFF)) || + (!cfg->vxlan.ip_version && (p->vxlan.ipv6.dscp > 0x3F)) || + (cfg->vxlan.vlan && (p->vxlan.vlan.vid > 0xFFF))) + return -1; + + if (cfg->vxlan.ip_version) + if (cfg->vxlan.vlan) { + struct encap_vxlan_ipv4_vlan_data *d = data; + + /* Ethernet */ + ether_addr_copy(&p->vxlan.ether.da, &d->ether.d_addr); + ether_addr_copy(&p->vxlan.ether.sa, &d->ether.s_addr); + d->ether.ether_type = rte_htons(ETHER_TYPE_VLAN); + + /* VLAN */ + d->vlan.vlan_tci = rte_htons(VLAN(p->vxlan.vlan.pcp, + p->vxlan.vlan.dei, + p->vxlan.vlan.vid)); + d->vlan.eth_proto = rte_htons(ETHER_TYPE_IPv4); + + /* IPv4*/ + d->ipv4.version_ihl = 0x45; + d->ipv4.type_of_service = p->vxlan.ipv4.dscp << 2; + d->ipv4.total_length = 0; /* not pre-computed */ + d->ipv4.packet_id = 0; + d->ipv4.fragment_offset = 0; + d->ipv4.time_to_live = p->vxlan.ipv4.ttl; + d->ipv4.next_proto_id = IP_PROTO_UDP; + d->ipv4.hdr_checksum = 0; + d->ipv4.src_addr = rte_htonl(p->vxlan.ipv4.sa); + d->ipv4.dst_addr = rte_htonl(p->vxlan.ipv4.da); + + d->ipv4.hdr_checksum = rte_ipv4_cksum(&d->ipv4); + + /* UDP */ + d->udp.src_port = rte_htons(p->vxlan.udp.sp); + d->udp.dst_port = rte_htons(p->vxlan.udp.dp); + d->udp.dgram_len = 0; /* not pre-computed */ + d->udp.dgram_cksum = 0; + + /* VXLAN */ + d->vxlan.vx_flags = rte_htonl(0x08000000); + d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8); + + return 0; + } else { + struct encap_vxlan_ipv4_data *d = data; + + /* Ethernet */ + ether_addr_copy(&p->vxlan.ether.da, &d->ether.d_addr); + ether_addr_copy(&p->vxlan.ether.sa, &d->ether.s_addr); + d->ether.ether_type = rte_htons(ETHER_TYPE_IPv4); + + /* IPv4*/ + d->ipv4.version_ihl = 0x45; + d->ipv4.type_of_service = p->vxlan.ipv4.dscp << 2; + d->ipv4.total_length = 0; /* not pre-computed */ + d->ipv4.packet_id = 0; + d->ipv4.fragment_offset = 0; + d->ipv4.time_to_live = p->vxlan.ipv4.ttl; + d->ipv4.next_proto_id = IP_PROTO_UDP; + d->ipv4.hdr_checksum = 0; + d->ipv4.src_addr = rte_htonl(p->vxlan.ipv4.sa); + d->ipv4.dst_addr = rte_htonl(p->vxlan.ipv4.da); + + d->ipv4.hdr_checksum = rte_ipv4_cksum(&d->ipv4); + + /* UDP */ + d->udp.src_port = rte_htons(p->vxlan.udp.sp); + d->udp.dst_port = rte_htons(p->vxlan.udp.dp); + d->udp.dgram_len = 0; /* not pre-computed */ + d->udp.dgram_cksum = 0; + + /* VXLAN */ + d->vxlan.vx_flags = rte_htonl(0x08000000); + d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8); + + return 0; + } + else + if (cfg->vxlan.vlan) { + struct encap_vxlan_ipv6_vlan_data *d = data; + + /* Ethernet */ + ether_addr_copy(&p->vxlan.ether.da, &d->ether.d_addr); + ether_addr_copy(&p->vxlan.ether.sa, &d->ether.s_addr); + d->ether.ether_type = rte_htons(ETHER_TYPE_VLAN); + + /* VLAN */ + d->vlan.vlan_tci = rte_htons(VLAN(p->vxlan.vlan.pcp, + p->vxlan.vlan.dei, + p->vxlan.vlan.vid)); + d->vlan.eth_proto = rte_htons(ETHER_TYPE_IPv6); + + /* IPv6*/ + d->ipv6.vtc_flow = rte_htonl((6 << 28) | + (p->vxlan.ipv6.dscp << 22) | + p->vxlan.ipv6.flow_label); + d->ipv6.payload_len = 0; /* not pre-computed */ + d->ipv6.proto = IP_PROTO_UDP; + d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit; + memcpy(d->ipv6.src_addr, + p->vxlan.ipv6.sa, + sizeof(p->vxlan.ipv6.sa)); + memcpy(d->ipv6.dst_addr, + p->vxlan.ipv6.da, + sizeof(p->vxlan.ipv6.da)); + + /* UDP */ + d->udp.src_port = rte_htons(p->vxlan.udp.sp); + d->udp.dst_port = rte_htons(p->vxlan.udp.dp); + d->udp.dgram_len = 0; /* not pre-computed */ + d->udp.dgram_cksum = 0; + + /* VXLAN */ + d->vxlan.vx_flags = rte_htonl(0x08000000); + d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8); + + return 0; + } else { + struct encap_vxlan_ipv6_data *d = data; + + /* Ethernet */ + ether_addr_copy(&p->vxlan.ether.da, &d->ether.d_addr); + ether_addr_copy(&p->vxlan.ether.sa, &d->ether.s_addr); + d->ether.ether_type = rte_htons(ETHER_TYPE_IPv6); + + /* IPv6*/ + d->ipv6.vtc_flow = rte_htonl((6 << 28) | + (p->vxlan.ipv6.dscp << 22) | + p->vxlan.ipv6.flow_label); + d->ipv6.payload_len = 0; /* not pre-computed */ + d->ipv6.proto = IP_PROTO_UDP; + d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit; + memcpy(d->ipv6.src_addr, + p->vxlan.ipv6.sa, + sizeof(p->vxlan.ipv6.sa)); + memcpy(d->ipv6.dst_addr, + p->vxlan.ipv6.da, + sizeof(p->vxlan.ipv6.da)); + + /* UDP */ + d->udp.src_port = rte_htons(p->vxlan.udp.sp); + d->udp.dst_port = rte_htons(p->vxlan.udp.dp); + d->udp.dgram_len = 0; /* not pre-computed */ + d->udp.dgram_cksum = 0; + + /* VXLAN */ + d->vxlan.vx_flags = rte_htonl(0x08000000); + d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8); + + return 0; + } +} + +static int encap_apply(void *data, struct rte_table_action_encap_params *p, struct rte_table_action_encap_config *cfg, @@ -707,11 +917,31 @@ encap_apply(void *data, case RTE_TABLE_ACTION_ENCAP_PPPOE: return encap_pppoe_apply(data, p); + case RTE_TABLE_ACTION_ENCAP_VXLAN: + return encap_vxlan_apply(data, p, cfg); + default: return -EINVAL; } } +static __rte_always_inline uint16_t +encap_vxlan_ipv4_checksum_update(uint16_t cksum0, + uint16_t total_length) +{ + int32_t cksum1; + + cksum1 = cksum0; + cksum1 = ~cksum1 & 0xFFFF; + + /* Add total length (one's complement logic) */ + cksum1 += total_length; + cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16); + cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16); + + return (uint16_t)(~cksum1); +} + static __rte_always_inline void * encap(void *dst, const void *src, size_t n) { @@ -720,6 +950,118 @@ encap(void *dst, const void *src, size_t n) } static __rte_always_inline void +pkt_work_encap_vxlan_ipv4(struct rte_mbuf *mbuf, + struct encap_vxlan_ipv4_data *vxlan_tbl, + struct rte_table_action_encap_config *cfg) +{ + uint32_t ether_offset = cfg->vxlan.data_offset; + void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset); + struct encap_vxlan_ipv4_data *vxlan_pkt; + uint16_t ether_length, ipv4_total_length, ipv4_hdr_cksum, udp_length; + + ether_length = (uint16_t)mbuf->pkt_len; + ipv4_total_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr) + + sizeof(struct ipv4_hdr)); + ipv4_hdr_cksum = encap_vxlan_ipv4_checksum_update(vxlan_tbl->ipv4.hdr_checksum, + rte_htons(ipv4_total_length)); + udp_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + + vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl)); + vxlan_pkt->ipv4.total_length = rte_htons(ipv4_total_length); + vxlan_pkt->ipv4.hdr_checksum = ipv4_hdr_cksum; + vxlan_pkt->udp.dgram_len = rte_htons(udp_length); + + mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt)); + mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt); +} + +static __rte_always_inline void +pkt_work_encap_vxlan_ipv4_vlan(struct rte_mbuf *mbuf, + struct encap_vxlan_ipv4_vlan_data *vxlan_tbl, + struct rte_table_action_encap_config *cfg) +{ + uint32_t ether_offset = cfg->vxlan.data_offset; + void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset); + struct encap_vxlan_ipv4_vlan_data *vxlan_pkt; + uint16_t ether_length, ipv4_total_length, ipv4_hdr_cksum, udp_length; + + ether_length = (uint16_t)mbuf->pkt_len; + ipv4_total_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr) + + sizeof(struct ipv4_hdr)); + ipv4_hdr_cksum = encap_vxlan_ipv4_checksum_update(vxlan_tbl->ipv4.hdr_checksum, + rte_htons(ipv4_total_length)); + udp_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + + vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl)); + vxlan_pkt->ipv4.total_length = rte_htons(ipv4_total_length); + vxlan_pkt->ipv4.hdr_checksum = ipv4_hdr_cksum; + vxlan_pkt->udp.dgram_len = rte_htons(udp_length); + + mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt)); + mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt); +} + +static __rte_always_inline void +pkt_work_encap_vxlan_ipv6(struct rte_mbuf *mbuf, + struct encap_vxlan_ipv6_data *vxlan_tbl, + struct rte_table_action_encap_config *cfg) +{ + uint32_t ether_offset = cfg->vxlan.data_offset; + void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset); + struct encap_vxlan_ipv6_data *vxlan_pkt; + uint16_t ether_length, ipv6_payload_length, udp_length; + + ether_length = (uint16_t)mbuf->pkt_len; + ipv6_payload_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + udp_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + + vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl)); + vxlan_pkt->ipv6.payload_len = rte_htons(ipv6_payload_length); + vxlan_pkt->udp.dgram_len = rte_htons(udp_length); + + mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt)); + mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt); +} + +static __rte_always_inline void +pkt_work_encap_vxlan_ipv6_vlan(struct rte_mbuf *mbuf, + struct encap_vxlan_ipv6_vlan_data *vxlan_tbl, + struct rte_table_action_encap_config *cfg) +{ + uint32_t ether_offset = cfg->vxlan.data_offset; + void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset); + struct encap_vxlan_ipv6_vlan_data *vxlan_pkt; + uint16_t ether_length, ipv6_payload_length, udp_length; + + ether_length = (uint16_t)mbuf->pkt_len; + ipv6_payload_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + udp_length = ether_length + + (sizeof(struct vxlan_hdr) + + sizeof(struct udp_hdr)); + + vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl)); + vxlan_pkt->ipv6.payload_len = rte_htons(ipv6_payload_length); + vxlan_pkt->udp.dgram_len = rte_htons(udp_length); + + mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt)); + mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt); +} + +static __rte_always_inline void pkt_work_encap(struct rte_mbuf *mbuf, void *data, struct rte_table_action_encap_config *cfg, @@ -776,6 +1118,20 @@ pkt_work_encap(struct rte_mbuf *mbuf, break; } + case 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN: + { + if (cfg->vxlan.ip_version) + if (cfg->vxlan.vlan) + pkt_work_encap_vxlan_ipv4_vlan(mbuf, data, cfg); + else + pkt_work_encap_vxlan_ipv4(mbuf, data, cfg); + else + if (cfg->vxlan.vlan) + pkt_work_encap_vxlan_ipv6_vlan(mbuf, data, cfg); + else + pkt_work_encap_vxlan_ipv6(mbuf, data, cfg); + } + default: break; } diff --git a/lib/librte_pipeline/rte_table_action.h b/lib/librte_pipeline/rte_table_action.h index c7f751a..73b564c 100644 --- a/lib/librte_pipeline/rte_table_action.h +++ b/lib/librte_pipeline/rte_table_action.h @@ -366,6 +366,11 @@ enum rte_table_action_encap_type { /** IP -> { Ether | PPPoE | PPP | IP } */ RTE_TABLE_ACTION_ENCAP_PPPOE, + + /** Ether -> { Ether | IP | UDP | VXLAN | Ether } + * Ether -> { Ether | VLAN | IP | UDP | VXLAN | Ether } + */ + RTE_TABLE_ACTION_ENCAP_VXLAN, }; /** Pre-computed Ethernet header fields for encapsulation action. */ @@ -393,6 +398,34 @@ struct rte_table_action_pppoe_hdr { uint16_t session_id; /**< Session ID. */ }; +/** Pre-computed IPv4 header fields for encapsulation action. */ +struct rte_table_action_ipv4_header { + uint32_t sa; /**< Source address. */ + uint32_t da; /**< Destination address. */ + uint8_t dscp; /**< DiffServ Code Point (DSCP). */ + uint8_t ttl; /**< Time To Live (TTL). */ +}; + +/** Pre-computed IPv6 header fields for encapsulation action. */ +struct rte_table_action_ipv6_header { + uint8_t sa[16]; /**< Source address. */ + uint8_t da[16]; /**< Destination address. */ + uint32_t flow_label; /**< Flow label. */ + uint8_t dscp; /**< DiffServ Code Point (DSCP). */ + uint8_t hop_limit; /**< Hop Limit (HL). */ +}; + +/** Pre-computed UDP header fields for encapsulation action. */ +struct rte_table_action_udp_header { + uint16_t sp; /**< Source port. */ + uint16_t dp; /**< Destination port. */ +}; + +/** Pre-computed VXLAN header fields for encapsulation action. */ +struct rte_table_action_vxlan_hdr { + uint32_t vni; /**< VXLAN Network Identifier (VNI). */ +}; + /** Ether encap parameters. */ struct rte_table_action_encap_ether_params { struct rte_table_action_ether_hdr ether; /**< Ethernet header. */ @@ -437,6 +470,21 @@ struct rte_table_action_encap_pppoe_params { struct rte_table_action_pppoe_hdr pppoe; /**< PPPoE/PPP headers. */ }; +/** VXLAN encap parameters. */ +struct rte_table_action_encap_vxlan_params { + struct rte_table_action_ether_hdr ether; /**< Ethernet header. */ + struct rte_table_action_vlan_hdr vlan; /**< VLAN header. */ + + RTE_STD_C11 + union { + struct rte_table_action_ipv4_header ipv4; /**< IPv4 header. */ + struct rte_table_action_ipv6_header ipv6; /**< IPv6 header. */ + }; + + struct rte_table_action_udp_header udp; /**< UDP header. */ + struct rte_table_action_vxlan_hdr vxlan; /**< VXLAN header. */ +}; + /** Encap action configuration (per table action profile). */ struct rte_table_action_encap_config { /** Bit mask defining the set of packet encapsulations enabled for the @@ -446,6 +494,30 @@ struct rte_table_action_encap_config { * @see enum rte_table_action_encap_type */ uint64_t encap_mask; + + /** Encapsulation type specific configuration. */ + RTE_STD_C11 + union { + struct { + /** Input packet to be encapsulated: offset within the + * input packet buffer to the start of the Ethernet + * frame to be encapsulated. Offset 0 points to the + * first byte of the MBUF structure. + */ + uint32_t data_offset; + + /** Encapsulation header: non-zero when encapsulation + * header includes a VLAN tag, zero otherwise. + */ + int vlan; + + /** Encapsulation header: IP version of the IP header + * within the encapsulation header. Non-zero for IPv4, + * zero for IPv6. + */ + int ip_version; + } vxlan; /**< VXLAN specific configuration. */ + }; }; /** Encap action parameters (per table rule). */ @@ -469,6 +541,9 @@ struct rte_table_action_encap_params { /** Only valid when *type* is set to PPPoE. */ struct rte_table_action_encap_pppoe_params pppoe; + + /** Only valid when *type* is set to VXLAN. */ + struct rte_table_action_encap_vxlan_params vxlan; }; }; From patchwork Fri Sep 7 15:58:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 44419 X-Patchwork-Delegate: cristian.dumitrescu@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 9CE6D4C9F; Fri, 7 Sep 2018 17:59:26 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 5AD453256 for ; Fri, 7 Sep 2018 17:59:23 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Sep 2018 08:59:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,343,1531810800"; d="scan'208";a="78757038" Received: from silpixa00382658.ir.intel.com ([10.237.223.29]) by FMSMGA003.fm.intel.com with ESMTP; 07 Sep 2018 08:59:03 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Date: Fri, 7 Sep 2018 16:58:51 +0100 Message-Id: <1536335931-171094-2-git-send-email-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1536335931-171094-1-git-send-email-cristian.dumitrescu@intel.com> References: <1536335931-171094-1-git-send-email-cristian.dumitrescu@intel.com> Subject: [dpdk-dev] [PATCH 2/2] examples/ip_pipeline: add vxlan encap X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add CLI support for VXLAN encap. Signed-off-by: Cristian Dumitrescu --- examples/ip_pipeline/cli.c | 181 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 4 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index 102a1d6..01c3769 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -961,7 +961,8 @@ static const char cmd_table_action_profile_help[] = " tc \n" " stats none | pkts | bytes | both]\n" " [tm spp pps ]\n" -" [encap ether | vlan | qinq | mpls | pppoe]\n" +" [encap ether | vlan | qinq | mpls | pppoe |\n" +" vxlan offset ipv4 | ipv6 vlan on | off]\n" " [nat src | dst\n" " proto udp | tcp]\n" " [ttl drop | fwd\n" @@ -1157,6 +1158,8 @@ cmd_table_action_profile(char **tokens, } /* tm */ if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) { + uint32_t n_extra_tokens = 0; + if (n_tokens < t0 + 2) { snprintf(out, out_size, MSG_ARG_MISMATCH, "action profile encap"); @@ -1173,13 +1176,61 @@ cmd_table_action_profile(char **tokens, p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; else if (strcmp(tokens[t0 + 1], "pppoe") == 0) p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; - else { + else if (strcmp(tokens[t0 + 1], "vxlan") == 0) { + if (n_tokens < t0 + 2 + 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "action profile encap vxlan"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "vxlan: offset"); + return; + } + + if (parser_read_uint32(&p.encap.vxlan.data_offset, + tokens[t0 + 2 + 1]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "vxlan: ether_offset"); + return; + } + + if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0) + p.encap.vxlan.ip_version = 1; + else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0) + p.encap.vxlan.ip_version = 0; + else { + snprintf(out, out_size, MSG_ARG_INVALID, + "vxlan: ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "vxlan: vlan"); + return; + } + + if (strcmp(tokens[t0 + 2 + 4], "on") == 0) + p.encap.vxlan.vlan = 1; + else if (strcmp(tokens[t0 + 2 + 4], "off") == 0) + p.encap.vxlan.vlan = 0; + else { + snprintf(out, out_size, MSG_ARG_INVALID, + "vxlan: on or off"); + return; + } + + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN; + n_extra_tokens = 5; + } else { snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); return; } p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; - t0 += 2; + t0 += 2 + n_extra_tokens; } /* encap */ if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) { @@ -2861,7 +2912,13 @@ parse_match(char **tokens, * [label1