summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/prox_cksum.c
diff options
context:
space:
mode:
authorDeepak S <deepak.s@linux.intel.com>2017-07-13 21:26:50 -0700
committerDeepak S <deepak.s@linux.intel.com>2017-07-14 04:58:47 -0700
commit7286b2518ec8e4398b512ce95def9166a7af2e4a (patch)
treec93ef65d9e73e8893ccecb720152e16aae96a8b6 /VNFs/DPPD-PROX/prox_cksum.c
parentadcb79da90176b27224eeb1d00aa0e611ef85a9b (diff)
Adding PROX(Packet pROcessing eXecution engine) VNF to sampleVNF
JIRA: SAMPLEVNF-55 PROX is a DPDK-based application implementing Telco use-cases such as a simplified BRAS/BNG, light-weight AFTR... It also allows configuring finer grained network functions like QoS, Routing, load-balancing... (We are moving PROX version v039 to sampleVNF https://01.org/intel-data-plane-performance-demonstrators/prox-overview) Change-Id: Ia3cb02cf0e49ac5596e922c197ff7e010293d033 Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Diffstat (limited to 'VNFs/DPPD-PROX/prox_cksum.c')
-rw-r--r--VNFs/DPPD-PROX/prox_cksum.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/prox_cksum.c b/VNFs/DPPD-PROX/prox_cksum.c
new file mode 100644
index 00000000..b69c06f6
--- /dev/null
+++ b/VNFs/DPPD-PROX/prox_cksum.c
@@ -0,0 +1,148 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "prox_cksum.h"
+#include "prox_port_cfg.h"
+#include <rte_byteorder.h>
+#include "log.h"
+
+/* compute IP 16 bit checksum */
+void prox_ip_cksum_sw(struct ipv4_hdr *buf)
+{
+ const uint16_t size = sizeof(struct ipv4_hdr);
+ uint32_t cksum = 0;
+ uint32_t nb_dwords;
+ uint32_t tail, mask;
+ uint32_t *pdwd = (uint32_t *)buf;
+
+ /* compute 16 bit checksum using hi and low parts of 32 bit integers */
+ for (nb_dwords = (size >> 2); nb_dwords > 0; --nb_dwords) {
+ cksum += (*pdwd >> 16);
+ cksum += (*pdwd & 0xFFFF);
+ ++pdwd;
+ }
+
+ /* deal with the odd byte length */
+ if (size & 0x03) {
+ tail = *pdwd;
+ /* calculate mask for valid parts */
+ mask = 0xFFFFFFFF << ((size & 0x03) << 3);
+ /* clear unused bits */
+ tail &= ~mask;
+
+ cksum += (tail >> 16) + (tail & 0xFFFF);
+ }
+
+ cksum = (cksum >> 16) + (cksum & 0xFFFF);
+ cksum = (cksum >> 16) + (cksum & 0xFFFF);
+
+ buf->hdr_checksum = ~((uint16_t)cksum);
+}
+
+static uint16_t calc_pseudo_checksum(uint8_t ipproto, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+{
+ uint32_t csum = 0;
+
+ csum += (src_ip_addr >> 16) + (src_ip_addr & 0xFFFF);
+ csum += (dst_ip_addr >> 16) + (dst_ip_addr & 0xFFFF);
+ csum += rte_bswap16(ipproto) + rte_bswap16(len);
+ csum = (csum >> 16) + (csum & 0xFFFF);
+ return csum;
+}
+
+static void prox_write_udp_pseudo_hdr(struct udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+{
+ /* Note that the csum is not complemented, while the pseaudo
+ header checksum is calculated as "... the 16-bit one's
+ complement of the one's complement sum of a pseudo header
+ of information ...", the psuedoheader forms as a basis for
+ the actual checksum calculated later either in software or
+ hardware. */
+ udp->dgram_cksum = calc_pseudo_checksum(IPPROTO_UDP, len, src_ip_addr, dst_ip_addr);
+}
+
+static void prox_write_tcp_pseudo_hdr(struct tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+{
+ tcp->cksum = calc_pseudo_checksum(IPPROTO_TCP, len, src_ip_addr, dst_ip_addr);
+}
+
+void prox_ip_udp_cksum(struct rte_mbuf *mbuf, struct ipv4_hdr *pip, uint16_t l2_len, uint16_t l3_len, int cksum_offload)
+{
+ prox_ip_cksum(mbuf, pip, l2_len, l3_len, cksum_offload & IPV4_CKSUM);
+
+#ifndef SOFT_CRC
+ if (cksum_offload & UDP_CKSUM)
+ mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
+#endif
+
+ uint32_t l4_len = rte_bswap16(pip->total_length) - l3_len;
+ if (pip->next_proto_id == IPPROTO_UDP) {
+ struct udp_hdr *udp = (struct udp_hdr *)(((uint8_t*)pip) + l3_len);
+#ifndef SOFT_CRC
+ if (cksum_offload & UDP_CKSUM)
+ prox_write_udp_pseudo_hdr(udp, l4_len, pip->src_addr, pip->dst_addr);
+ else
+#endif
+ prox_udp_cksum_sw(udp, l4_len, pip->src_addr, pip->dst_addr);
+ } else if (pip->next_proto_id == IPPROTO_TCP) {
+ struct tcp_hdr *tcp = (struct tcp_hdr *)(((uint8_t*)pip) + l3_len);
+#ifndef SOFT_CRC
+ if (cksum_offload & UDP_CKSUM)
+ prox_write_tcp_pseudo_hdr(tcp, l4_len, pip->src_addr, pip->dst_addr);
+ else
+#endif
+ prox_tcp_cksum_sw(tcp, l4_len, pip->src_addr, pip->dst_addr);
+ }
+}
+
+static uint16_t checksum_byte_seq(uint16_t *buf, uint16_t len)
+{
+ uint32_t csum = 0;
+
+ while (len > 1) {
+ csum += *buf;
+ while (csum >> 16) {
+ csum &= 0xffff;
+ csum +=1;
+ }
+ buf++;
+ len -= 2;
+ }
+
+ if (len) {
+ csum += *(uint8_t*)buf;
+ while (csum >> 16) {
+ csum &= 0xffff;
+ csum +=1;
+ }
+ }
+ return ~csum;
+}
+
+void prox_udp_cksum_sw(struct udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+{
+ prox_write_udp_pseudo_hdr(udp, len, src_ip_addr, dst_ip_addr);
+ uint16_t csum = checksum_byte_seq((uint16_t *)udp, len);
+ udp->dgram_cksum = csum;
+}
+
+void prox_tcp_cksum_sw(struct tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr)
+{
+ prox_write_tcp_pseudo_hdr(tcp, len, src_ip_addr, dst_ip_addr);
+
+ uint16_t csum = checksum_byte_seq((uint16_t *)tcp, len);
+ tcp->cksum = csum;
+}