Line data Source code
1 : #ifndef HEADER_fd_src_waltz_ip_fd_ip_h
2 : #define HEADER_fd_src_waltz_ip_fd_ip_h
3 :
4 : #include "fd_ip_enum.h"
5 : #include "fd_netlink.h"
6 : #include "../../util/fd_util.h"
7 :
8 : /* implements a number of IP protocol functions required by XDP, since we're bypassing
9 : parts of the kernel */
10 :
11 :
12 : /* ARP
13 :
14 : We use netlink to retrieve the ARP table
15 :
16 : Whenever an IP we're trying to resolve is not in the ARP table, we'll simply send an
17 : ARP request. The Kernel should see the responses and update its ARP table
18 :
19 : */
20 :
21 : /* Routing
22 :
23 : We use netlink to obtain the routing table
24 :
25 : In particular we need to choose which next hop IP is required
26 :
27 : */
28 :
29 : /* magic */
30 6 : #define FD_IP_MAGIC (0x37ad94a6ec098fc1UL)
31 :
32 : /* size of an ARP probe packet, including eth header */
33 0 : #define FD_IP_ARP_SZ (sizeof(fd_ip_arp_t))
34 :
35 : /* alias fd_ip_route_entry_t to fd_nl_route_entry_t
36 : and fd_ip_arp_entry_t to fd_nl_arp_entry_t */
37 : typedef fd_nl_route_entry_t fd_ip_route_entry_t;
38 : typedef fd_nl_arp_entry_t fd_ip_arp_entry_t;
39 :
40 : struct fd_ip {
41 : ulong magic;
42 :
43 : /* capacity */
44 : ulong num_arp_entries;
45 : ulong num_route_entries;
46 :
47 : /* current state */
48 : ulong cur_num_arp_entries;
49 : ulong cur_num_route_entries;
50 :
51 : /* table index */
52 : /* there are two arp tables and two route tables */
53 : /* these indicate whether the current table is the first or second */
54 : uint arp_table_idx;
55 : uint route_table_idx;
56 :
57 : ulong ofs_netlink;
58 : ulong ofs_arp_table;
59 : ulong ofs_route_table;
60 : };
61 : typedef struct fd_ip fd_ip_t;
62 :
63 :
64 : struct fd_ip_arp {
65 : /* Ethernet header */
66 : uchar dst_mac_addr[6]; /* broadcast address */
67 : uchar src_mac_addr[6]; /* source mac address */
68 : ushort ethtype; /* Ethertype - ARP is 0x0806 */
69 :
70 : /* ARP */
71 : ushort hw_type; /* Ethernet is 1 */
72 : ushort proto_type; /* IP is 0x0800 */
73 : uchar hw_addr_len; /* hardware address length - ethernet is 6 */
74 : uchar proto_addr_len; /* protocol address length - IPv4 is 4 */
75 : ushort op; /* operation - request is 1 */
76 : uchar sender_hw_addr[6]; /* sender hardware address */
77 : uchar sender_proto_addr[4]; /* sender protocol (IPv4) address */
78 : uchar target_hw_addr[6]; /* target hardware address - ignored for request */
79 : uchar target_proto_addr[4]; /* target protocol (IPv4) address - ignored for request */
80 :
81 : };
82 : typedef struct fd_ip_arp fd_ip_arp_t;
83 :
84 :
85 : FD_PROTOTYPES_BEGIN
86 :
87 : /* footprint and align
88 :
89 : obtain the required footprint and alignment */
90 :
91 12 : #define FD_IP_ALIGN (64UL)
92 :
93 : FD_FN_CONST ulong fd_ip_footprint( ulong arp_entries, ulong routing_entries );
94 : FD_FN_CONST ulong fd_ip_align( void );
95 :
96 :
97 : /* new IP
98 :
99 : create IP stack in the workspace
100 :
101 : arp_entries the maximum number of arp entries allowed
102 : routing_entries the maximum number ot routing entries allowed
103 :
104 : returns
105 : a void pointer to the value required by fd_ip_join */
106 :
107 : void *
108 : fd_ip_new( void * shmem, ulong arp_entries, ulong routing_entries );
109 :
110 :
111 : /* join existing IP stack
112 :
113 : joins the IP stack that already exists in the workspace
114 :
115 : returns pointer to the fd_ip_t instance or NULL in a failure
116 :
117 : only one join to each fd_ip_t per process is allowed
118 : each join creates a netlink file descriptor
119 :
120 : args
121 : mem the return value from fd_ip_new
122 :
123 : returns
124 : pointer to the fd_ip_t joined for use, or NULL if an error occurred */
125 :
126 :
127 : fd_ip_t *
128 : fd_ip_join( void * mem );
129 :
130 :
131 : /* leave the fd_ip
132 :
133 : cleans up local resources
134 : the supplied ip pointer should not be used after
135 :
136 : args
137 : ip the fd_ip to leave */
138 : void *
139 : fd_ip_leave( fd_ip_t * ip );
140 :
141 :
142 : /* get pointer to netlink
143 : this is used internally */
144 : fd_nl_t *
145 : fd_ip_netlink_get( fd_ip_t * ip );
146 :
147 :
148 : /* get pointer to start of current routing table
149 : this is used internally
150 : probably best not to modify the data */
151 : fd_ip_route_entry_t *
152 : fd_ip_route_table_get( fd_ip_t * ip );
153 :
154 :
155 : /* get pointer to start of alternate routing table
156 : this is used internally
157 : probably best not to modify the data */
158 : fd_ip_route_entry_t *
159 : fd_ip_route_table_get_alt( fd_ip_t * ip );
160 :
161 :
162 : /* get pointer to start of current arp table
163 : this is used internally
164 : probably best not to modify the data */
165 : fd_ip_arp_entry_t *
166 : fd_ip_arp_table_get( fd_ip_t * ip );
167 :
168 :
169 : /* get pointer to start of alternate arp table
170 : this is used internally
171 : probably best not to modify the data */
172 : fd_ip_arp_entry_t *
173 : fd_ip_arp_table_get_alt( fd_ip_t * ip );
174 :
175 :
176 : /* fetch the ARP table from the kernel
177 :
178 : The table is written into the workspace
179 :
180 : use fd_ip_arp_query to access the data */
181 :
182 : void
183 : fd_ip_arp_fetch( fd_ip_t * ip );
184 :
185 :
186 : /* query an arp entry
187 :
188 : searches for an IP address in the table
189 :
190 : if found, *arp is set to point to the entry and the function
191 : returns FD_IP_SUCCESS
192 :
193 : otherwise, the function returns FD_IP_ERROR */
194 :
195 : int
196 : fd_ip_arp_query( fd_ip_t * ip, fd_ip_arp_entry_t ** arp, uint ip_addr );
197 :
198 :
199 : /* generate a raw ARP probe (request) packet
200 :
201 : used for caller to generate an ARP packet to send in the event
202 : we don't have an existing ARP entry
203 :
204 : writes ARP packet into buf
205 :
206 : if successful, returns FD_IP_SUCCESS
207 :
208 : if unable to generate ARP, if the dest capacity (dest_cap) is not enough space
209 : then the function returns FD_IP_ERROR
210 :
211 : args
212 : buf the buffer used to accept the raw ethernet packet
213 : buf_cap the capacity in bytes of buf
214 : arp_len *arp_len is set to the length in bytes of the generated ARP packet
215 : ip_addr the IPv4 address of the target to be probed
216 : src_mac_addr the MAC address of the source (caller)
217 :
218 : returns
219 : FD_IP_SUCCESS on success
220 : FD_IP_ERROR on failure (buf_cap not large enough) */
221 :
222 : int
223 : fd_ip_arp_gen_arp_probe( uchar * buf,
224 : ulong buf_cap,
225 : ulong * arp_len,
226 : uint dst_ip_addr,
227 : uint src_ip_addr,
228 : uchar const * src_mac_addr );
229 :
230 :
231 : /* fetch the routing table from the kernel
232 :
233 : the routing table will be written into the workspace, completely replacing
234 : any existing routing entries */
235 :
236 : void
237 : fd_ip_route_fetch( fd_ip_t * ip );
238 :
239 :
240 : /* query the routing table
241 :
242 : the provided IP address is looked up in the routing table
243 :
244 : if an appropriate entry is found, *route is set to point to it
245 : and FD_IP_SUCCESS is returned
246 :
247 : otherwise, FD_IP_ERROR is returned */
248 :
249 : int
250 : fd_ip_route_query( fd_ip_t * ip,
251 : fd_ip_route_entry_t ** route,
252 : uint ip_addr );
253 :
254 :
255 : /* Do routing for an ip_addr
256 :
257 : Handles unicast, broadcast and multicast
258 : broadcast:
259 : ff.ff.ff.ff -> mac: ff:ff:ff:ff:ff:ff
260 : subnet broadcast:
261 : a.ff.ff.ff/8
262 : a.b.ff.ff/16
263 : a.b.c.ff/24 -> if local, ff:ff:ff:ff:ff:ff
264 : else normal routing
265 : multicast:
266 : 224+a,b,c,d -> 01:00:5e:B:c:d (B = b & 0x7f)
267 :
268 : Queries the routing table
269 : If no match return -1 error
270 : If match,
271 : Determines which ip_addr to use
272 : If local, uses dst_ip_addr
273 : Else, uses the gateway/next hop ip addr
274 : Queries the arp table
275 : If no match returns 1 - send probe
276 : If match, sets mac and ifindex and returns 0
277 :
278 : returns
279 : FD_IP_NO_ROUTE No route to destination
280 : FD_IP_SUCCESS Route (and arp if necessary) found. out_* have been set
281 : FD_IP_PROBE_RQD Route, but we need to send an ARP probe to resolve the MAC address
282 : Resolve the supplied out_next_ip_addr by sending a probe packet
283 : Delay between probes
284 : FD_IP_MULTICAST Multicast
285 : FD_IP_BROADCAST Local broadcast */
286 : int
287 : fd_ip_route_ip_addr( uchar * out_dst_mac,
288 : uint * out_next_ip_addr,
289 : uint * out_ifindex,
290 : fd_ip_t * ip,
291 : uint ip_addr );
292 :
293 :
294 : /* Prepares the ARP cache for receiving a new ARP entry
295 :
296 : Should be called prior to sending an ARP request
297 :
298 : The kernel ignores unsolicited ARP responses, so this function
299 : allows our ARP requests to update the kernel ARP table
300 :
301 : It creates or updates an entry depending on the current state
302 : If there is no entry, it creates one in state NONE
303 : Otherwise, it moves NONE to INCOMPLETE and moves DELAY to PROBE
304 : This should give the kernel what it needs to handle the rest of
305 : the transitions correctly
306 :
307 : return values:
308 : FD_IP_SUCCESS Call successful, nothing to do
309 : FD_IP_PROBE Call successful, caller should send an ARP probe
310 : FD_IP_RETRY Call successful, caller should try this call again soon
311 : or immediately
312 : FD_IP_ERROR Call unsuccessful */
313 : int
314 : fd_ip_update_arp_table( fd_ip_t * ip,
315 : uint ip_addr,
316 : uint ifindex );
317 :
318 : FD_PROTOTYPES_END
319 :
320 : #endif
|