-
Notifications
You must be signed in to change notification settings - Fork 0
/
sr_arpcache.h
executable file
·155 lines (123 loc) · 5.57 KB
/
sr_arpcache.h
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* This file defines an ARP cache, which is made of two structures: an ARP
request queue, and ARP cache entries. The ARP request queue holds data about
an outgoing ARP cache request and the packets that are waiting on a reply
to that ARP cache request. The ARP cache entries hold IP->MAC mappings and
are timed out every SR_ARPCACHE_TO seconds.
Pseudocode for use of these structures follows.
--
# When sending packet to next_hop_ip
entry = arpcache_lookup(next_hop_ip)
if entry:
use next_hop_ip->mac mapping in entry to send the packet
free entry
else:
req = arpcache_queuereq(next_hop_ip, packet, len)
handle_arpreq(req)
--
The handle_arpreq() function is a function you should write, and it should
handle sending ARP requests if necessary:
function handle_arpreq(req):
if difftime(now, req->sent) > 1.0
if req->times_sent >= 5:
send icmp host unreachable to source addr of all pkts waiting
on this request
arpreq_destroy(req)
else:
send arp request
req->sent = now
req->times_sent++
--
The ARP reply processing code should move entries from the ARP request
queue to the ARP cache:
# When servicing an arp reply that gives us an IP->MAC mapping
req = arpcache_insert(ip, mac)
if req:
send all packets on the req->packets linked list
arpreq_destroy(req)
--
To meet the guidelines in the assignment (ARP requests are sent every second
until we send 5 ARP requests, then we send ICMP host unreachable back to
all packets waiting on this ARP request), you must fill out the following
function that is called every second.
void sr_arpcache_sweepreqs(struct sr_instance *sr) {
for each request on sr->cache.requests:
handle_arpreq(request)
}
Since handle_arpreq as defined in the comments above could destroy your
current request, make sure to save the next pointer before calling
handle_arpreq when traversing through the ARP requests linked list.
*/
#ifndef SR_ARPCACHE_H
#define SR_ARPCACHE_H
#include <inttypes.h>
#include <time.h>
#include <pthread.h>
#include "sr_if.h"
#define SR_ARPCACHE_SZ 100
#define SR_ARPCACHE_TO 15.0
struct sr_packet {
uint8_t *buf; /* A raw Ethernet frame, presumably with the dest MAC empty */
unsigned int len; /* Length of raw Ethernet frame */
char *iface; /* The outgoing interface */
struct sr_packet *next;
};
struct sr_arpentry {
unsigned char mac[6];
uint32_t ip; /* IP addr in network byte order */
time_t added;
int valid;
};
struct sr_arpreq {
uint32_t ip;
time_t sent; /* Last time this ARP request was sent. You
should update this. If the ARP request was
never sent, will be 0. */
uint32_t times_sent; /* Number of times this request was sent. You
should update this. */
struct sr_packet *packets; /* List of pkts waiting on this req to finish */
struct sr_arpreq *next;
};
struct sr_arpcache {
struct sr_arpentry entries[SR_ARPCACHE_SZ];
struct sr_arpreq *requests;
pthread_mutex_t lock;
pthread_mutexattr_t attr;
};
/* Checks if an IP->MAC mapping is in the cache. IP is in network byte order.
You must free the returned structure if it is not NULL. */
struct sr_arpentry *sr_arpcache_lookup(struct sr_arpcache *cache, uint32_t ip);
/* Adds an ARP request to the ARP request queue. If the request is already on
the queue, adds the packet to the linked list of packets for this sr_arpreq
that corresponds to this ARP request. The packet argument should not be
freed by the caller.
A pointer to the ARP request is returned; it should not be freed. The caller
can remove the ARP request from the queue by calling sr_arpreq_destroy. */
struct sr_arpreq *sr_arpcache_queuereq(struct sr_arpcache *cache,
uint32_t ip,
uint8_t *packet, /* borrowed */
unsigned int packet_len,
char *iface);
/* This function gets called every second. For each request sent out, we keep
checking whether we should resend an request or destroy the ARP request.
See pseudo-code in sr_arpcache.h*/
void sr_arpcache_sweepreqs(struct sr_instance *sr);
/* This method performs two functions:
1) Looks up this IP in the request queue. If it is found, returns a pointer
to the sr_arpreq with this IP. Otherwise, returns NULL.
2) Inserts this IP to MAC mapping in the cache, and marks it valid. */
struct sr_arpreq *sr_arpcache_insert(struct sr_arpcache *cache,
unsigned char *mac,
uint32_t ip);
/* Frees all memory associated with this arp request entry. If this arp request
entry is on the arp request queue, it is removed from the queue. */
void sr_arpreq_destroy(struct sr_arpcache *cache, struct sr_arpreq *entry);
/* Prints out the ARP table. */
void sr_arpcache_dump(struct sr_arpcache *cache);
/* You shouldn't have to call these methods--they're already called in the
starter code for you. The init call is a constructor, the destroy call is
a destructor, and a cleanup thread times out cache entries every 15
seconds. */
int sr_arpcache_init(struct sr_arpcache *cache);
int sr_arpcache_destroy(struct sr_arpcache *cache);
void *sr_arpcache_timeout(void *cache_ptr);
#endif