32 #include <packet_defs.h> 36 #define ARP_DEBUG(x...) do { } while (0) 42 uint8_t mac[ETH_ADDR_LEN];
52 static inline int response_tx(
const void *dst_mac, uint32_t dst_ip);
53 static inline int request_tx(uint32_t dst_ip);
54 static inline struct arp_entry *ae_lookup(uint32_t ip);
56 static struct arp_entry *arp_table = NULL;
66 memcpy(lb->mac, &
eth_addr, ETH_ADDR_LEN);
73 memcpy(&mac, &
eth_addr, ETH_ADDR_LEN);
76 printf(
"host ip: %x MAC: %lx\n", config.
ip, mac);
88 if ((ae = ae_lookup(ip)) != NULL) {
89 if (ae->status == 0) {
90 ARP_DEBUG(
"lookup succeeded (%x)\n", ip);
91 memcpy(mac, ae->mac, 6);
95 ARP_DEBUG(
"request still pending (%x)\n", ip);
97 comp->el.next = (
void *) ae->compl;
104 if ((ae = malloc(
sizeof(*ae))) == NULL) {
105 fprintf(stderr,
"arp_request: malloc failed\n");
112 comp->el.next = NULL;
116 if (request_tx(ip) != 0) {
118 fprintf(stderr,
"arp_timeout: sending out request failed\n");
122 ae->timeout = config.
arp_to;
127 ae->next = arp_table;
128 if (arp_table != NULL) {
129 arp_table->prev = ae;
133 ARP_DEBUG(
"request sent (%x)\n", ip);
140 const struct pkt_arp *parp = pkt;
141 const struct arp_hdr *arp = &parp->arp;
149 if (f_beui16(arp->htype) != ARP_HTYPE_ETHERNET ||
150 f_beui16(arp->ptype) != ARP_PTYPE_IPV4 ||
151 arp->hlen != 6 || arp->plen != 4)
153 fprintf(stderr,
"arp_packet: Invalid packet received htype=%x ptype=%x " 154 "hlen=%x plen=%x\n", f_beui16(arp->htype), f_beui16(arp->ptype),
155 arp->hlen, arp->plen);
158 op = f_beui16(arp->oper);
159 if (op == ARP_OPER_REQUEST) {
161 ARP_DEBUG(
"arp request received (%x)\n", f_beui32(arp->spa));
162 if (f_beui32(arp->tpa) != config.
ip) {
168 if (response_tx(&arp->sha, f_beui32(arp->spa)) != 0) {
169 fprintf(stderr,
"arp_packet: sending response failed\n");
172 }
else if (op == ARP_OPER_REPLY) {
173 ARP_DEBUG(
"arp reply received (%x)\n", f_beui32(arp->spa));
176 if ((ae = ae_lookup(f_beui32(arp->spa))) == NULL) {
177 ARP_DEBUG(stderr,
"arp_packet: response has no entry\n");
181 if (ae->status == 1) {
187 memcpy(ae->mac, &arp->sha, ETH_ADDR_LEN);
191 for (comp = ae->compl; comp != NULL; comp = comp_next) {
192 comp_next = (
void *) comp->el.next;
194 memcpy(comp->ptr, ae->mac, ETH_ADDR_LEN);
196 fd = comp->notify_fd;
197 nbqueue_enq(comp->q, &comp->el);
199 ret = write(fd, &cnt,
sizeof(cnt));
201 perror(
"arp_packet: error writing to notify fd");
216 ((uintptr_t) to - offsetof(
struct arp_entry, to));
218 ARP_DEBUG(
"arp_timeout(%x): timeout=%uus\n", ae->ip, ae->timeout);
222 if (ae->status == 0) {
223 fprintf(stderr,
"arp_timeout: arp entry marked as ready\n");
229 ARP_DEBUG(
"arp_timeout: request for %x timed out\n", ae->ip);
232 for (comp = ae->compl; comp != NULL; comp = comp_next) {
233 comp_next = (
void *) comp->el.next;
236 fd = comp->notify_fd;
237 nbqueue_enq(comp->q, &comp->el);
239 ret = write(fd, &cnt,
sizeof(cnt));
241 perror(
"arp_packet: error writing to notify fd");
247 if (ae->prev != NULL) {
248 ae->prev->next = ae->next;
250 arp_table = ae->next;
252 if (ae->next != NULL) {
253 ae->next->prev = ae->prev;
262 if (request_tx(ae->ip) != 0) {
263 fprintf(stderr,
"arp_timeout: sending out request failed\n");
271 static inline int response_tx(
const void *dst_mac, uint32_t dst_ip)
277 if (
nicif_tx_alloc(
sizeof(*parp_out), (
void **) &parp_out, &new_tail) != 0) {
282 memcpy(&parp_out->eth.src, &
eth_addr, ETH_ADDR_LEN);
283 memcpy(&parp_out->arp.sha, &
eth_addr, ETH_ADDR_LEN);
284 memcpy(&parp_out->eth.dest, dst_mac, ETH_ADDR_LEN);
285 memcpy(&parp_out->arp.tha, dst_mac, ETH_ADDR_LEN);
286 parp_out->arp.spa = t_beui32(config.
ip);
287 parp_out->arp.tpa = t_beui32(dst_ip);
289 parp_out->eth.type = t_beui16(ETH_TYPE_ARP);
291 parp_out->arp.htype = t_beui16(ARP_HTYPE_ETHERNET);
292 parp_out->arp.ptype = t_beui16(ARP_PTYPE_IPV4);
293 parp_out->arp.hlen = 6;
294 parp_out->arp.plen = 4;
295 parp_out->arp.oper = t_beui16(ARP_OPER_REPLY);
302 static inline int request_tx(uint32_t dst_ip)
306 uint64_t dst_mac = 0xffffffffffffULL;
309 if (
nicif_tx_alloc(
sizeof(*parp_out), (
void **) &parp_out, &new_tail) != 0) {
314 memcpy(&parp_out->eth.src, &
eth_addr, ETH_ADDR_LEN);
315 memcpy(&parp_out->arp.sha, &
eth_addr, ETH_ADDR_LEN);
316 memcpy(&parp_out->eth.dest, &dst_mac, ETH_ADDR_LEN);
317 memcpy(&parp_out->arp.tha, &dst_mac, ETH_ADDR_LEN);
318 parp_out->arp.spa = t_beui32(config.
ip);
319 parp_out->arp.tpa = t_beui32(dst_ip);
321 parp_out->eth.type = t_beui16(ETH_TYPE_ARP);
323 parp_out->arp.htype = t_beui16(ARP_HTYPE_ETHERNET);
324 parp_out->arp.ptype = t_beui16(ARP_PTYPE_IPV4);
325 parp_out->arp.hlen = 6;
326 parp_out->arp.plen = 4;
327 parp_out->arp.oper = t_beui16(ARP_OPER_REQUEST);
334 static inline struct arp_entry *ae_lookup(uint32_t ip)
338 for (ae = arp_table; ae != NULL; ae = ae->next) {
int arp_request(struct nicif_completion *comp, uint32_t ip, uint64_t *mac)
void arp_packet(const void *pkt, uint16_t len)
void arp_timeout(struct timeout *to, enum timeout_type type)
void util_timeout_disarm(struct timeout_manager *mgr, struct timeout *to)
int nicif_tx_alloc(uint16_t len, void **buf, uint32_t *opaque)
void nicif_tx_send(uint32_t opaque, int no_ts)
void util_timeout_arm(struct timeout_manager *mgr, struct timeout *to, uint32_t us, uint8_t type)