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 <iostream>
13 : #include <sstream>
14 : #include <iomanip>
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 :
38 0 : memset(arp, 0, sizeof(struct rte_arp_hdr));
39 0 : rte_memcpy(&arp->arp_data.arp_sha, &mac_addr, 6);
40 :
41 0 : inetAddrCopy(&arp->arp_data.arp_sip, &ip_add_bin);
42 :
43 0 : rte_memcpy(&arp->arp_data.arp_tha, &mac_addr, 6);
44 0 : inetAddrCopy(&arp->arp_data.arp_tip, &ip_add_bin);
45 :
46 : /* Fill in the rest of the ARP packet header */
47 0 : arp->arp_hardware = htons(RTE_ARP_HRD_ETHER);
48 0 : arp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4);
49 0 : arp->arp_hlen = 6;
50 0 : arp->arp_plen = 4;
51 0 : arp->arp_opcode = htons(RTE_ARP_OP_REQUEST);
52 :
53 0 : m->pkt_len = 60;
54 0 : m->data_len = 60;
55 :
56 0 : struct rte_mbuf *arp_tx_mbuf[1];
57 0 : arp_tx_mbuf[0] = m;
58 :
59 :
60 0 : std::string srcaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_sip)));
61 0 : std::string dstaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(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(dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(ip_add_bin)));
63 0 : TLOG_DEBUG(10) << "GARP SRC IP: " << srcaddr;
64 0 : TLOG_DEBUG(10) << "GARP DEST IP: " << dstaddr;
65 0 : TLOG_DEBUG(10) << "LOCAL IP: " << localaddr;
66 :
67 0 : rte_eth_tx_burst(port_id, 0, arp_tx_mbuf, 1);
68 0 : }
69 :
70 :
71 : inline void
72 : hex_digits_to_stream(std::ostringstream& ostrs, int value, char separator = ':', char fill = '0', int digits = 2) {
73 : ostrs << std::setfill(fill) << std::setw(digits) << std::hex << value << std::dec << separator;
74 : }
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 :
87 : /* Grab the source MAC addresses */
88 0 : struct rte_ether_addr mac_addr;
89 0 : rte_eth_macaddr_get(port_id, &mac_addr);
90 :
91 0 : std::string srcaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(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(dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(arp->arp_data.arp_tip)));
93 0 : std::string localaddr = dunedaq::dpdklibs::udp::get_ipv4_decimal_addr_str(dunedaq::dpdklibs::udp::ip_address_binary_to_dotdecimal(rte_be_to_cpu_32(ip_add_bin)));
94 :
95 0 : TLOG_DEBUG(10) << "ARP SRC IP: " << srcaddr;
96 0 : TLOG_DEBUG(10) << "ARP DEST IP: " << dstaddr;
97 0 : TLOG_DEBUG(10) << "ARP LOCAL IP: " << localaddr;
98 :
99 : // Bail out if not our ipaddress
100 0 : if ( arp->arp_data.arp_tip != ip_add_bin) return;
101 :
102 0 : TLOG_DEBUG(10) << "ARP Received " << dstaddr << " I'm the target " << localaddr << " (port id = " << port_id << ")";
103 :
104 : /* Swap the two MAC addresses */
105 0 : ethAddrSwap(&arp->arp_data.arp_sha, &arp->arp_data.arp_tha);
106 :
107 : /* Swap the two IP addresses */
108 0 : inetAddrSwap(&arp->arp_data.arp_tip, &arp->arp_data.arp_sip);
109 :
110 : /* Set the packet to ARP reply */
111 0 : arp->arp_opcode = htons(RTE_ARP_OP_REPLY);
112 :
113 : /* Swap the MAC addresses */
114 0 : ethAddrSwap(ð->dst_addr, ð->src_addr);
115 :
116 : /* Copy in the MAC address for the reply. */
117 0 : rte_memcpy(&arp->arp_data.arp_sha, &mac_addr, 6);
118 0 : rte_memcpy(ð->src_addr, &mac_addr, 6);
119 :
120 0 : struct rte_mbuf *arp_tx_mbuf[1];
121 0 : arp_tx_mbuf[0] = m;
122 :
123 0 : rte_eth_tx_burst(port_id, 0, arp_tx_mbuf, 1);
124 0 : TLOG_DEBUG(10) << "Sending ARP reply";
125 :
126 : /* No need to free mbuf as it was reused */
127 0 : return;
128 0 : }
129 : }
130 :
131 : } // namespace arp
132 : } // namespace dpdklibs
133 : } // namespace dunedaq
|