summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/arp.h
blob: ebf8a89e9ee61b67f01ea59601818751cfaa6de0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
// 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.
*/

#ifndef _ARP_H_
#define _ARP_H_

#include <rte_ether.h>
#include "prox_compat.h"
#include "etypes.h"
#include "mbuf_utils.h"

#define ARP_REQUEST	0x100
#define ARP_REPLY	0x200

struct _arp_ipv4 {
	prox_rte_ether_addr sha; /* Sender hardware address */
	uint32_t spa;          /* Sender protocol address */
	prox_rte_ether_addr tha; /* Target hardware address */
	uint32_t tpa;          /* Target protocol address */
} __attribute__((__packed__)) __attribute__((__aligned__(2)));
typedef struct _arp_ipv4 arp_ipv4_t;

struct my_arp_t {
	uint16_t   htype;
	uint16_t   ptype;
	uint8_t    hlen;
	uint8_t    plen;
	uint16_t   oper;
	arp_ipv4_t data;
} __attribute__((__packed__)) __attribute__((__aligned__(2)));

struct ether_hdr_arp {
	prox_rte_ether_hdr ether_hdr;
	struct my_arp_t arp;
};

static int arp_is_gratuitous(struct my_arp_t *arp)
{
	return arp->data.spa == arp->data.tpa;
}

// This build an arp reply based on a an request
static inline void build_arp_reply(prox_rte_ether_hdr *ether_hdr, prox_rte_ether_addr *s_addr, struct my_arp_t *arp)
{
	uint32_t ip_source = arp->data.spa;

	memcpy(ether_hdr->d_addr.addr_bytes, ether_hdr->s_addr.addr_bytes, sizeof(prox_rte_ether_addr));
	memcpy(ether_hdr->s_addr.addr_bytes, s_addr, sizeof(prox_rte_ether_addr));

	arp->data.spa = arp->data.tpa;
	arp->data.tpa = ip_source;
	arp->oper = 0x200;
	memcpy(&arp->data.tha, &arp->data.sha, sizeof(prox_rte_ether_addr));
	memcpy(&arp->data.sha, s_addr, sizeof(prox_rte_ether_addr));
}

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)
{
	struct ether_hdr_arp *hdr_arp;
	prox_rte_vlan_hdr *vlan_hdr;
	prox_rte_ether_hdr *ether_hdr;
	struct my_arp_t *arp;
	uint64_t mac_bcast = 0xFFFFFFFFFFFF;
	init_mbuf_seg(mbuf);

	if (vlan) {
		ether_hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
		vlan_hdr = (prox_rte_vlan_hdr *)(ether_hdr + 1);
		arp = (struct my_arp_t *)(vlan_hdr + 1);
		ether_hdr->ether_type = ETYPE_VLAN;
		vlan_hdr->eth_proto = ETYPE_ARP;
		vlan_hdr->vlan_tci = rte_cpu_to_be_16(vlan);
		rte_pktmbuf_pkt_len(mbuf) = 42 + sizeof(prox_rte_vlan_hdr);
		rte_pktmbuf_data_len(mbuf) = 42 + sizeof(prox_rte_vlan_hdr);
	} else {
		ether_hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
		arp = (struct my_arp_t *)(ether_hdr + 1);
		ether_hdr->ether_type = ETYPE_ARP;
		rte_pktmbuf_pkt_len(mbuf) = 42;
		rte_pktmbuf_data_len(mbuf) = 42;
	}

	memcpy(&ether_hdr->d_addr.addr_bytes, &mac_bcast, 6);
	memcpy(&ether_hdr->s_addr.addr_bytes, src_mac, 6);
	arp->htype = 0x100,
	arp->ptype = 0x0008;
	arp->hlen = 6;
	arp->plen = 4;
	arp->oper = 0x100;
	arp->data.spa = ip_src;
	arp->data.tpa = ip_dst;
	memset(&arp->data.tha, 0, sizeof(prox_rte_ether_addr));
	memcpy(&arp->data.sha, src_mac, sizeof(prox_rte_ether_addr));
}

static void create_mac(struct my_arp_t *arp, prox_rte_ether_addr *addr)
{
        addr->addr_bytes[0] = 0x2;
        addr->addr_bytes[1] = 0;
        // Instead of sending a completely random MAC address, create the following MAC:
        // 02:00:x1:x2:x3:x4 where x1:x2:x3:x4 is the IP address
        memcpy(addr->addr_bytes + 2, (uint32_t *)&arp->data.tpa, 4);
}

#endif /* _ARP_H_ */