Support packets in flight
[samplevnf.git] / VNFs / DPPD-PROX / arp.h
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #ifndef _ARP_H_
18 #define _ARP_H_
19
20 #include <rte_ether.h>
21 #include "prox_compat.h"
22 #include "etypes.h"
23 #include "mbuf_utils.h"
24
25 #define ARP_REQUEST     0x100
26 #define ARP_REPLY       0x200
27
28 struct _arp_ipv4 {
29         prox_rte_ether_addr sha; /* Sender hardware address */
30         uint32_t spa;          /* Sender protocol address */
31         prox_rte_ether_addr tha; /* Target hardware address */
32         uint32_t tpa;          /* Target protocol address */
33 } __attribute__((__packed__)) __attribute__((__aligned__(2)));
34 typedef struct _arp_ipv4 arp_ipv4_t;
35
36 struct my_arp_t {
37         uint16_t   htype;
38         uint16_t   ptype;
39         uint8_t    hlen;
40         uint8_t    plen;
41         uint16_t   oper;
42         arp_ipv4_t data;
43 } __attribute__((__packed__)) __attribute__((__aligned__(2)));
44
45 struct ether_hdr_arp {
46         prox_rte_ether_hdr ether_hdr;
47         struct my_arp_t arp;
48 };
49
50 static int arp_is_gratuitous(struct my_arp_t *arp)
51 {
52         return arp->data.spa == arp->data.tpa;
53 }
54
55 // This build an arp reply based on a an request
56 static inline void build_arp_reply(prox_rte_ether_hdr *ether_hdr, prox_rte_ether_addr *s_addr, struct my_arp_t *arp)
57 {
58         uint32_t ip_source = arp->data.spa;
59
60         memcpy(ether_hdr->d_addr.addr_bytes, ether_hdr->s_addr.addr_bytes, sizeof(prox_rte_ether_addr));
61         memcpy(ether_hdr->s_addr.addr_bytes, s_addr, sizeof(prox_rte_ether_addr));
62
63         arp->data.spa = arp->data.tpa;
64         arp->data.tpa = ip_source;
65         arp->oper = 0x200;
66         memcpy(&arp->data.tha, &arp->data.sha, sizeof(prox_rte_ether_addr));
67         memcpy(&arp->data.sha, s_addr, sizeof(prox_rte_ether_addr));
68 }
69
70 static inline void build_arp_request(struct rte_mbuf *mbuf, prox_rte_ether_addr *src_mac, uint32_t ip_dst, uint32_t ip_src, uint16_t vlan)
71 {
72         struct ether_hdr_arp *hdr_arp;
73         prox_rte_vlan_hdr *vlan_hdr;
74         prox_rte_ether_hdr *ether_hdr;
75         struct my_arp_t *arp;
76         uint64_t mac_bcast = 0xFFFFFFFFFFFF;
77         init_mbuf_seg(mbuf);
78
79         if (vlan) {
80                 ether_hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
81                 vlan_hdr = (prox_rte_vlan_hdr *)(ether_hdr + 1);
82                 arp = (struct my_arp_t *)(vlan_hdr + 1);
83                 ether_hdr->ether_type = ETYPE_VLAN;
84                 vlan_hdr->eth_proto = ETYPE_ARP;
85                 vlan_hdr->vlan_tci = rte_cpu_to_be_16(vlan);
86                 rte_pktmbuf_pkt_len(mbuf) = 42 + sizeof(prox_rte_vlan_hdr);
87                 rte_pktmbuf_data_len(mbuf) = 42 + sizeof(prox_rte_vlan_hdr);
88         } else {
89                 ether_hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
90                 arp = (struct my_arp_t *)(ether_hdr + 1);
91                 ether_hdr->ether_type = ETYPE_ARP;
92                 rte_pktmbuf_pkt_len(mbuf) = 42;
93                 rte_pktmbuf_data_len(mbuf) = 42;
94         }
95
96         memcpy(&ether_hdr->d_addr.addr_bytes, &mac_bcast, 6);
97         memcpy(&ether_hdr->s_addr.addr_bytes, src_mac, 6);
98         arp->htype = 0x100,
99         arp->ptype = 0x0008;
100         arp->hlen = 6;
101         arp->plen = 4;
102         arp->oper = 0x100;
103         arp->data.spa = ip_src;
104         arp->data.tpa = ip_dst;
105         memset(&arp->data.tha, 0, sizeof(prox_rte_ether_addr));
106         memcpy(&arp->data.sha, src_mac, sizeof(prox_rte_ether_addr));
107 }
108
109 static void create_mac(struct my_arp_t *arp, prox_rte_ether_addr *addr)
110 {
111         addr->addr_bytes[0] = 0x2;
112         addr->addr_bytes[1] = 0;
113         // Instead of sending a completely random MAC address, create the following MAC:
114         // 02:00:x1:x2:x3:x4 where x1:x2:x3:x4 is the IP address
115         memcpy(addr->addr_bytes + 2, (uint32_t *)&arp->data.tpa, 4);
116 }
117
118 #endif /* _ARP_H_ */