Line data Source code
1 : /**
2 : * @file ARP.cpp ARP helpers implementation
3 : *
4 : * This is part of the DUNE DAQ , copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 : #include <arpa/inet.h>
9 : #include <rte_arp.h>
10 : #include <rte_ethdev.h>
11 :
12 : #include <iomanip>
13 : #include <iostream>
14 : #include <sstream>
15 :
16 : #include "dpdklibs/arp/ARP.hpp"
17 :
18 : namespace dunedaq {
19 : namespace dpdklibs {
20 : namespace arp {
21 :
22 : void
23 0 : pktgen_send_garp(struct rte_mbuf* m, uint32_t port_id, rte_be32_t ip_add_bin)
24 : {
25 0 : struct rte_ether_hdr* eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr*);
26 0 : struct rte_arp_hdr* arp = (struct rte_arp_hdr*)ð[1];
27 :
28 : /* src and dest addr */
29 0 : memset(ð->dst_addr, 0xFF, 6);
30 : // MAC addr of port
31 0 : struct rte_ether_addr mac_addr;
32 0 : rte_eth_macaddr_get(port_id, &mac_addr);
33 0 : rte_ether_addr_copy(&mac_addr, ð->src_addr);
34 : // Set ETH type
35 0 : eth->ether_type = htons(RTE_ETHER_TYPE_ARP);
36 :
37 0 : memset(arp, 0, sizeof(struct rte_arp_hdr));
38 0 : rte_memcpy(&arp->arp_data.arp_sha, &mac_addr, 6);
39 :
40 0 : inetAddrCopy(&arp->arp_data.arp_sip, &ip_add_bin);
41 :
42 0 : rte_memcpy(&arp->arp_data.arp_tha, &mac_addr, 6);
43 0 : inetAddrCopy(&arp->arp_data.arp_tip, &ip_add_bin);
44 :
45 : /* Fill in the rest of the ARP packet header */
46 0 : arp->arp_hardware = htons(RTE_ARP_HRD_ETHER);
47 0 : arp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4);
48 0 : arp->arp_hlen = 6;
49 0 : arp->arp_plen = 4;
50 0 : arp->arp_opcode = htons(RTE_ARP_OP_REQUEST);
51 :
52 0 : m->pkt_len = 60;
53 0 : m->data_len = 60;
54 :
55 0 : struct rte_mbuf* arp_tx_mbuf[1];
56 0 : arp_tx_mbuf[0] = m;
57 :
58 0 : std::string srcaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
59 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_sip)));
60 0 : std::string dstaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
61 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_tip)));
62 0 : std::string localaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
63 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(ip_add_bin)));
64 0 : TLOG_DEBUG(10) << "GARP SRC IP: " << srcaddr;
65 0 : TLOG_DEBUG(10) << "GARP DEST IP: " << dstaddr;
66 0 : TLOG_DEBUG(10) << "LOCAL IP: " << localaddr;
67 :
68 0 : rte_eth_tx_burst(port_id, 0, arp_tx_mbuf, 1);
69 0 : }
70 :
71 : inline void
72 : hex_digits_to_stream(std::ostringstream& ostrs, int value, char separator = ':', char fill = '0', int digits = 2)
73 : {
74 : ostrs << std::setfill(fill) << std::setw(digits) << std::hex << value << std::dec << separator;
75 : }
76 :
77 : void
78 0 : pktgen_process_arp(struct rte_mbuf* m, uint32_t port_id, rte_be32_t ip_add_bin)
79 : {
80 0 : struct rte_ether_hdr* eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr*);
81 0 : struct rte_arp_hdr* arp = (struct rte_arp_hdr*)ð[1];
82 :
83 0 : if (arp->arp_opcode == rte_cpu_to_be_16(RTE_ARP_OP_REQUEST)) {
84 0 : arp->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
85 :
86 : /* Grab the source MAC addresses */
87 0 : struct rte_ether_addr mac_addr;
88 0 : rte_eth_macaddr_get(port_id, &mac_addr);
89 :
90 0 : std::string srcaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
91 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_sip)));
92 0 : std::string dstaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
93 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_tip)));
94 0 : std::string localaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(
95 0 : dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(ip_add_bin)));
96 :
97 0 : TLOG_DEBUG(10) << "ARP SRC IP: " << srcaddr;
98 0 : TLOG_DEBUG(10) << "ARP DEST IP: " << dstaddr;
99 0 : TLOG_DEBUG(10) << "ARP LOCAL IP: " << localaddr;
100 :
101 : // Bail out if not our ipaddress
102 0 : if (arp->arp_data.arp_tip != ip_add_bin)
103 : return;
104 :
105 0 : TLOG_DEBUG(10) << "ARP Received " << dstaddr << " I'm the target " << localaddr << " (port id = " << port_id << ")";
106 :
107 : /* Swap the two MAC addresses */
108 0 : ethAddrSwap(&arp->arp_data.arp_sha, &arp->arp_data.arp_tha);
109 :
110 : /* Swap the two IP addresses */
111 0 : inetAddrSwap(&arp->arp_data.arp_tip, &arp->arp_data.arp_sip);
112 :
113 : /* Set the packet to ARP reply */
114 0 : arp->arp_opcode = htons(RTE_ARP_OP_REPLY);
115 :
116 : /* Swap the MAC addresses */
117 0 : ethAddrSwap(ð->dst_addr, ð->src_addr);
118 :
119 : /* Copy in the MAC address for the reply. */
120 0 : rte_memcpy(&arp->arp_data.arp_sha, &mac_addr, 6);
121 0 : rte_memcpy(ð->src_addr, &mac_addr, 6);
122 :
123 0 : struct rte_mbuf* arp_tx_mbuf[1];
124 0 : arp_tx_mbuf[0] = m;
125 :
126 0 : rte_eth_tx_burst(port_id, 0, arp_tx_mbuf, 1);
127 0 : TLOG_DEBUG(10) << "Sending ARP reply";
128 :
129 : /* No need to free mbuf as it was reused */
130 0 : return;
131 0 : }
132 : }
133 :
134 : } // namespace arp
135 : } // namespace dpdklibs
136 : } // namespace dunedaq
|