Print this page
Restore SVP_R_ROUTE_REQ, and all that goes with it.
Interpret sl3a_uport == 0 in SVP_R_VL3_ACK to indicate the VL3 IP is a next-hop router.
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/varpd/svp/common/libvarpd_svp_remote.c
+++ new/usr/src/lib/varpd/svp/common/libvarpd_svp_remote.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2018 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Remote backend management
18 18 *
19 19 * For more information, see the big theory statement in
20 20 * lib/varpd/svp/common/libvarpd_svp.c.
21 21 */
22 22
23 23 #include <umem.h>
24 24 #include <strings.h>
25 25 #include <string.h>
26 26 #include <stddef.h>
27 27 #include <thread.h>
28 28 #include <synch.h>
29 29 #include <assert.h>
30 30 #include <sys/socket.h>
31 31 #include <netdb.h>
32 32 #include <errno.h>
33 33 #include <libidspace.h>
34 34
35 35 #include <libvarpd_provider.h>
36 36 #include <libvarpd_svp.h>
37 37
38 38 typedef struct svp_shoot_vl3 {
39 39 svp_query_t ssv_query;
40 40 struct sockaddr_in6 ssv_sock;
41 41 svp_log_vl3_t *ssv_vl3;
42 42 svp_sdlog_t *ssv_log;
43 43 } svp_shoot_vl3_t;
44 44
45 45 static mutex_t svp_remote_lock = ERRORCHECKMUTEX;
46 46 static avl_tree_t svp_remote_tree;
47 47 static svp_timer_t svp_dns_timer;
48 48 static id_space_t *svp_idspace;
49 49 static int svp_dns_timer_rate = 30; /* seconds */
50 50
51 51 static void
52 52 svp_remote_mkfmamsg(svp_remote_t *srp, svp_degrade_state_t state, char *buf,
53 53 size_t buflen)
54 54 {
55 55 switch (state) {
56 56 case SVP_RD_DNS_FAIL:
57 57 (void) snprintf(buf, buflen, "failed to resolve or find "
58 58 "entries for hostname %s", srp->sr_hostname);
59 59 break;
60 60 case SVP_RD_REMOTE_FAIL:
61 61 (void) snprintf(buf, buflen, "cannot reach any remote peers");
62 62 break;
63 63 default:
64 64 (void) snprintf(buf, buflen, "unkonwn error state: %d", state);
65 65 }
66 66 }
67 67
68 68 static int
69 69 svp_remote_comparator(const void *l, const void *r)
70 70 {
71 71 int ret;
72 72 const svp_remote_t *lr = l, *rr = r;
73 73
74 74 ret = strcmp(lr->sr_hostname, rr->sr_hostname);
75 75 if (ret > 0)
76 76 return (1);
77 77 else if (ret < 0)
78 78 return (-1);
79 79
80 80 if (lr->sr_rport > rr->sr_rport)
81 81 return (1);
82 82 else if (lr->sr_rport < rr->sr_rport)
83 83 return (-1);
84 84
85 85 return (memcmp(&lr->sr_uip, &rr->sr_uip, sizeof (struct in6_addr)));
86 86 }
87 87
88 88 void
89 89 svp_query_release(svp_query_t *sqp)
90 90 {
91 91 id_free(svp_idspace, sqp->sq_header.svp_id);
92 92 }
93 93
94 94 static void
95 95 svp_remote_destroy(svp_remote_t *srp)
96 96 {
97 97 size_t len;
98 98
99 99 /*
100 100 * Clean up any unrelated DNS information. At this point we know that
101 101 * we're not in the remote tree. That means, that svp_remote_dns_timer
102 102 * cannot queue us. However, if any of our DNS related state flags are
103 103 * set, we have to hang out.
104 104 */
105 105 mutex_enter(&srp->sr_lock);
106 106 while (srp->sr_state &
107 107 (SVP_RS_LOOKUP_SCHEDULED | SVP_RS_LOOKUP_INPROGRESS)) {
108 108 (void) cond_wait(&srp->sr_cond, &srp->sr_lock);
109 109 }
110 110 mutex_exit(&srp->sr_lock);
111 111 svp_shootdown_fini(srp);
112 112
113 113 if (cond_destroy(&srp->sr_cond) != 0)
114 114 libvarpd_panic("failed to destroy cond sr_cond");
115 115
116 116 if (mutex_destroy(&srp->sr_lock) != 0)
117 117 libvarpd_panic("failed to destroy mutex sr_lock");
118 118
119 119 if (srp->sr_addrinfo != NULL)
120 120 freeaddrinfo(srp->sr_addrinfo);
121 121 len = strlen(srp->sr_hostname) + 1;
122 122 umem_free(srp->sr_hostname, len);
123 123 umem_free(srp, sizeof (svp_remote_t));
124 124 }
125 125
126 126 static int
127 127 svp_remote_create(const char *host, uint16_t port, struct in6_addr *uip,
128 128 svp_remote_t **outp)
129 129 {
130 130 size_t hlen;
131 131 svp_remote_t *remote;
132 132
133 133 assert(MUTEX_HELD(&svp_remote_lock));
134 134
135 135 remote = umem_zalloc(sizeof (svp_remote_t), UMEM_DEFAULT);
136 136 if (remote == NULL) {
137 137 mutex_exit(&svp_remote_lock);
138 138 return (ENOMEM);
139 139 }
140 140
141 141 if (svp_shootdown_init(remote) != 0) {
142 142 umem_free(remote, sizeof (svp_remote_t));
143 143 mutex_exit(&svp_remote_lock);
144 144 return (ENOMEM);
145 145 }
146 146
147 147 hlen = strlen(host) + 1;
148 148 remote->sr_hostname = umem_alloc(hlen, UMEM_DEFAULT);
149 149 if (remote->sr_hostname == NULL) {
150 150 svp_shootdown_fini(remote);
151 151 umem_free(remote, sizeof (svp_remote_t));
152 152 mutex_exit(&svp_remote_lock);
153 153 return (ENOMEM);
154 154 }
155 155 remote->sr_rport = port;
156 156 if (mutex_init(&remote->sr_lock,
157 157 USYNC_THREAD | LOCK_ERRORCHECK, NULL) != 0)
158 158 libvarpd_panic("failed to create mutex sr_lock");
159 159 if (cond_init(&remote->sr_cond, USYNC_PROCESS, NULL) != 0)
160 160 libvarpd_panic("failed to create cond sr_cond");
161 161 list_create(&remote->sr_conns, sizeof (svp_conn_t),
162 162 offsetof(svp_conn_t, sc_rlist));
163 163 avl_create(&remote->sr_tree, svp_comparator, sizeof (svp_t),
164 164 offsetof(svp_t, svp_rlink));
165 165 (void) strlcpy(remote->sr_hostname, host, hlen);
166 166 remote->sr_count = 1;
167 167 remote->sr_uip = *uip;
168 168
169 169 svp_shootdown_start(remote);
170 170
171 171 *outp = remote;
172 172 return (0);
173 173 }
174 174
175 175 int
176 176 svp_remote_find(char *host, uint16_t port, struct in6_addr *uip,
177 177 svp_remote_t **outp)
178 178 {
179 179 int ret;
180 180 svp_remote_t lookup, *remote;
181 181
182 182 lookup.sr_hostname = host;
183 183 lookup.sr_rport = port;
184 184 lookup.sr_uip = *uip;
185 185 mutex_enter(&svp_remote_lock);
186 186 remote = avl_find(&svp_remote_tree, &lookup, NULL);
187 187 if (remote != NULL) {
188 188 assert(remote->sr_count > 0);
189 189 remote->sr_count++;
190 190 *outp = remote;
191 191 mutex_exit(&svp_remote_lock);
192 192 return (0);
193 193 }
194 194
195 195 if ((ret = svp_remote_create(host, port, uip, outp)) != 0) {
196 196 mutex_exit(&svp_remote_lock);
197 197 return (ret);
198 198 }
199 199
200 200 avl_add(&svp_remote_tree, *outp);
201 201 mutex_exit(&svp_remote_lock);
202 202
203 203 /* Make sure DNS is up to date */
204 204 svp_host_queue(*outp);
205 205
206 206 return (0);
207 207 }
208 208
209 209 void
210 210 svp_remote_release(svp_remote_t *srp)
211 211 {
212 212 mutex_enter(&svp_remote_lock);
213 213 mutex_enter(&srp->sr_lock);
214 214 srp->sr_count--;
215 215 if (srp->sr_count != 0) {
216 216 mutex_exit(&srp->sr_lock);
217 217 mutex_exit(&svp_remote_lock);
218 218 return;
219 219 }
220 220 mutex_exit(&srp->sr_lock);
221 221
222 222 avl_remove(&svp_remote_tree, srp);
223 223 mutex_exit(&svp_remote_lock);
224 224 svp_remote_destroy(srp);
225 225 }
226 226
227 227 int
228 228 svp_remote_attach(svp_remote_t *srp, svp_t *svp)
229 229 {
230 230 svp_t check;
231 231 avl_index_t where;
232 232
233 233 mutex_enter(&srp->sr_lock);
234 234 if (svp->svp_remote != NULL)
235 235 libvarpd_panic("failed to create mutex sr_lock");
236 236
237 237 /*
|
↓ open down ↓ |
237 lines elided |
↑ open up ↑ |
238 238 * We require everything except shootdowns
239 239 */
240 240 if (svp->svp_cb.scb_vl2_lookup == NULL)
241 241 libvarpd_panic("missing callback scb_vl2_lookup");
242 242 if (svp->svp_cb.scb_vl3_lookup == NULL)
243 243 libvarpd_panic("missing callback scb_vl3_lookup");
244 244 if (svp->svp_cb.scb_vl2_invalidate == NULL)
245 245 libvarpd_panic("missing callback scb_vl2_invalidate");
246 246 if (svp->svp_cb.scb_vl3_inject == NULL)
247 247 libvarpd_panic("missing callback scb_vl3_inject");
248 - if (svp->svp_cb.scb_rvl3_lookup == NULL)
249 - libvarpd_panic("missing callback scb_rvl3_lookup");
248 + if (svp->svp_cb.scb_route_lookup == NULL)
249 + libvarpd_panic("missing callback scb_route_lookup");
250 250
251 251 check.svp_vid = svp->svp_vid;
252 252 if (avl_find(&srp->sr_tree, &check, &where) != NULL)
253 253 libvarpd_panic("found duplicate entry with vid %ld",
254 254 svp->svp_vid);
255 255 avl_insert(&srp->sr_tree, svp, where);
256 256 svp->svp_remote = srp;
257 257 mutex_exit(&srp->sr_lock);
258 258
259 259 return (0);
260 260 }
261 261
262 262 void
263 263 svp_remote_detach(svp_t *svp)
264 264 {
265 265 svp_t *lookup;
266 266 svp_remote_t *srp = svp->svp_remote;
267 267
268 268 if (srp == NULL)
269 269 libvarpd_panic("trying to detach remote when none exists");
270 270
271 271 mutex_enter(&srp->sr_lock);
272 272 lookup = avl_find(&srp->sr_tree, svp, NULL);
273 273 if (lookup == NULL || lookup != svp)
274 274 libvarpd_panic("inconsitent remote avl tree...");
275 275 avl_remove(&srp->sr_tree, svp);
276 276 svp->svp_remote = NULL;
277 277 mutex_exit(&srp->sr_lock);
278 278 svp_remote_release(srp);
279 279 }
280 280
281 281 /*
282 282 * Walk the list of connections and find the first one that's available, the
283 283 * move it to the back of the list so it's less likely to be used again.
284 284 */
285 285 static boolean_t
286 286 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
287 287 {
288 288 svp_conn_t *scp;
289 289
290 290 assert(MUTEX_HELD(&srp->sr_lock));
291 291 for (scp = list_head(&srp->sr_conns); scp != NULL;
292 292 scp = list_next(&srp->sr_conns, scp)) {
293 293 mutex_enter(&scp->sc_lock);
294 294 if (scp->sc_cstate != SVP_CS_ACTIVE) {
295 295 mutex_exit(&scp->sc_lock);
296 296 continue;
297 297 }
298 298 svp_conn_queue(scp, sqp);
299 299 mutex_exit(&scp->sc_lock);
300 300 list_remove(&srp->sr_conns, scp);
301 301 list_insert_tail(&srp->sr_conns, scp);
302 302 return (B_TRUE);
303 303 }
304 304
305 305 return (B_FALSE);
306 306 }
307 307
308 308 static void
309 309 svp_remote_vl2_lookup_cb(svp_query_t *sqp, void *arg)
310 310 {
311 311 svp_t *svp = sqp->sq_svp;
312 312 svp_vl2_ack_t *vl2a = (svp_vl2_ack_t *)sqp->sq_wdata;
313 313
314 314 if (sqp->sq_status == SVP_S_OK)
315 315 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status,
316 316 (struct in6_addr *)vl2a->sl2a_addr, ntohs(vl2a->sl2a_port),
317 317 arg);
318 318 else
319 319 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status, NULL, 0, arg);
320 320 }
321 321
322 322 void
323 323 svp_remote_vl2_lookup(svp_t *svp, svp_query_t *sqp, const uint8_t *mac,
324 324 void *arg)
325 325 {
326 326 svp_remote_t *srp;
327 327 svp_vl2_req_t *vl2r = &sqp->sq_rdun.sqd_vl2r;
328 328
329 329 srp = svp->svp_remote;
330 330 sqp->sq_func = svp_remote_vl2_lookup_cb;
331 331 sqp->sq_arg = arg;
332 332 sqp->sq_svp = svp;
333 333 sqp->sq_state = SVP_QUERY_INIT;
334 334 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
335 335 sqp->sq_header.svp_op = htons(SVP_R_VL2_REQ);
336 336 sqp->sq_header.svp_size = htonl(sizeof (svp_vl2_req_t));
337 337 sqp->sq_header.svp_id = id_alloc(svp_idspace);
338 338 if (sqp->sq_header.svp_id == (id_t)-1)
339 339 libvarpd_panic("failed to allcoate from svp_idspace: %d",
340 340 errno);
341 341 sqp->sq_header.svp_crc32 = htonl(0);
342 342 sqp->sq_rdata = vl2r;
343 343 sqp->sq_rsize = sizeof (svp_vl2_req_t);
344 344 sqp->sq_wdata = NULL;
345 345 sqp->sq_wsize = 0;
346 346
|
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
347 347 bcopy(mac, vl2r->sl2r_mac, ETHERADDRL);
348 348 vl2r->sl2r_vnetid = ntohl(svp->svp_vid);
349 349
350 350 mutex_enter(&srp->sr_lock);
351 351 if (svp_remote_conn_queue(srp, sqp) == B_FALSE)
352 352 svp->svp_cb.scb_vl2_lookup(svp, SVP_S_FATAL, NULL, NULL, arg);
353 353 mutex_exit(&srp->sr_lock);
354 354 }
355 355
356 356 static void
357 -svp_remote_rvl3_lookup_cb(svp_query_t *sqp, void *arg)
357 +svp_remote_route_lookup_cb(svp_query_t *sqp, void *arg)
358 358 {
359 359 svp_t *svp = sqp->sq_svp;
360 - svp_rvl3_ack_t *rvl3a = (svp_rvl3_ack_t *)sqp->sq_wdata;
360 + svp_route_ack_t *sra = (svp_route_ack_t *)sqp->sq_wdata;
361 361
362 362 if (sqp->sq_status == SVP_S_OK) {
363 - svp->svp_cb.scb_rvl3_lookup(svp, sqp->sq_status,
364 - /* XXX KEBE SAYS MORE HERE */ arg);
363 + svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
364 + sra->sra_dcid, sra->sra_vnetid, sra->sra_vlan,
365 + sra->sra_srcmac, sra->sra_dstmac, sra->sra_port,
366 + sra->sra_ip, sra->sra_src_pfx, sra->sra_dst_pfx, arg);
365 367 } else {
368 + svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
369 + 0, 0, 0, NULL, NULL, 0, NULL, 0, 0, arg);
366 370 }
367 371 }
368 372
369 373 void
370 -svp_remote_rvl3_lookup(svp_t *svp, svp_query_t *sqp, const struct in6_addr *src,
371 - const struct in6_addr *dst, uint32_t type, uint32_t vnetid, uint16_t vlan,
372 - void *arg)
374 +svp_remote_route_lookup(svp_t *svp, svp_query_t *sqp,
375 + const struct in6_addr *src, const struct in6_addr *dst, uint32_t vnetid,
376 + uint16_t vlan, void *arg)
373 377 {
374 378 svp_remote_t *srp;
375 - svp_rvl3_req_t *rvl3r = &sqp->sq_rdun.sqd_rvl3r;
379 + svp_route_req_t *srr = &sqp->sq_rdun.sqd_rr;
376 380
377 381 srp = svp->svp_remote;
378 - sqp->sq_func = svp_remote_rvl3_lookup_cb;
382 + sqp->sq_func = svp_remote_route_lookup_cb;
379 383 sqp->sq_arg = arg;
380 384 sqp->sq_svp = svp;
381 385 sqp->sq_state = SVP_QUERY_INIT;
382 386 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
383 - sqp->sq_header.svp_op = htons(SVP_R_REMOTE_VL3_REQ);
384 - sqp->sq_header.svp_size = htonl(sizeof (svp_vl2_req_t));
387 + sqp->sq_header.svp_op = htons(SVP_R_ROUTE_REQ);
388 + sqp->sq_header.svp_size = htonl(sizeof (svp_route_req_t));
385 389 sqp->sq_header.svp_id = id_alloc(svp_idspace);
386 390 if (sqp->sq_header.svp_id == (id_t)-1)
387 391 libvarpd_panic("failed to allcoate from svp_idspace: %d",
388 392 errno);
389 393 sqp->sq_header.svp_crc32 = htonl(0);
390 - sqp->sq_rdata = rvl3r;
394 + sqp->sq_rdata = srr;
391 395
392 - bcopy(src, rvl3r->srl3r_srcip, sizeof (struct in6_addr));
393 - bcopy(dst, rvl3r->srl3r_dstip, sizeof (struct in6_addr));
396 + bcopy(src, srr->srr_srcip, sizeof (struct in6_addr));
397 + bcopy(dst, srr->srr_dstip, sizeof (struct in6_addr));
394 398 /* Caller should've checked both are the same type... */
395 - rvl3r->srl3r_type = type;
396 - rvl3r->srl3r_vnetid = vnetid;
397 - rvl3r->srl3r_vlan = vlan;
398 - rvl3r->srl3r_pad = 0;
399 + srr->srr_vnetid = vnetid;
400 + srr->srr_vlan = vlan;
401 + srr->srr_pad = 0;
399 402
400 403 mutex_enter(&srp->sr_lock);
401 404 if (!svp_remote_conn_queue(srp, sqp)) {
402 405 sqp->sq_status = SVP_S_FATAL;
403 406 sqp->sq_func(sqp, arg);
404 407 }
405 408 mutex_exit(&srp->sr_lock);
406 409 }
407 410
408 411 static void
409 412 svp_remote_vl3_lookup_cb(svp_query_t *sqp, void *arg)
410 413 {
411 414 svp_t *svp = sqp->sq_svp;
412 415 svp_vl3_ack_t *vl3a = (svp_vl3_ack_t *)sqp->sq_wdata;
413 416
414 417 if (sqp->sq_status == SVP_S_OK)
415 418 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, vl3a->sl3a_mac,
416 419 (struct in6_addr *)vl3a->sl3a_uip, ntohs(vl3a->sl3a_uport),
417 420 arg);
418 421 else
419 422 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, NULL, NULL, 0,
420 423 arg);
421 424 }
422 425
423 426 static void
424 427 svp_remote_vl3_common(svp_remote_t *srp, svp_query_t *sqp,
425 428 const struct sockaddr *addr, svp_query_f func, void *arg, uint32_t vid)
426 429 {
427 430 svp_vl3_req_t *vl3r = &sqp->sq_rdun.sdq_vl3r;
428 431
429 432 if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
430 433 libvarpd_panic("unexpected sa_family for the vl3 lookup");
431 434
432 435 sqp->sq_func = func;
433 436 sqp->sq_arg = arg;
434 437 sqp->sq_state = SVP_QUERY_INIT;
435 438 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
436 439 sqp->sq_header.svp_op = htons(SVP_R_VL3_REQ);
437 440 sqp->sq_header.svp_size = htonl(sizeof (svp_vl3_req_t));
438 441 sqp->sq_header.svp_id = id_alloc(svp_idspace);
439 442 if (sqp->sq_header.svp_id == (id_t)-1)
440 443 libvarpd_panic("failed to allcoate from svp_idspace: %d",
441 444 errno);
442 445 sqp->sq_header.svp_crc32 = htonl(0);
443 446 sqp->sq_rdata = vl3r;
444 447 sqp->sq_rsize = sizeof (svp_vl3_req_t);
445 448 sqp->sq_wdata = NULL;
446 449 sqp->sq_wsize = 0;
447 450
448 451 if (addr->sa_family == AF_INET6) {
449 452 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)addr;
450 453 vl3r->sl3r_type = htonl(SVP_VL3_IPV6);
451 454 bcopy(&s6->sin6_addr, vl3r->sl3r_ip,
452 455 sizeof (struct in6_addr));
453 456 } else {
454 457 struct sockaddr_in *s4 = (struct sockaddr_in *)addr;
455 458 struct in6_addr v6;
456 459
457 460 vl3r->sl3r_type = htonl(SVP_VL3_IP);
458 461 IN6_INADDR_TO_V4MAPPED(&s4->sin_addr, &v6);
459 462 bcopy(&v6, vl3r->sl3r_ip, sizeof (struct in6_addr));
460 463 }
461 464 vl3r->sl3r_vnetid = htonl(vid);
462 465
463 466 mutex_enter(&srp->sr_lock);
464 467 if (svp_remote_conn_queue(srp, sqp) == B_FALSE) {
465 468 sqp->sq_status = SVP_S_FATAL;
466 469 sqp->sq_func(sqp, arg);
467 470 }
468 471 mutex_exit(&srp->sr_lock);
469 472 }
470 473
471 474 /*
472 475 * This is a request to do a VL3 look-up that originated internally as opposed
473 476 * to coming from varpd. As such we need a slightly different query callback
474 477 * function upon completion and don't go through the normal path with the svp_t.
475 478 */
476 479 void
477 480 svp_remote_vl3_logreq(svp_remote_t *srp, svp_query_t *sqp, uint32_t vid,
478 481 const struct sockaddr *addr, svp_query_f func, void *arg)
479 482 {
480 483 svp_remote_vl3_common(srp, sqp, addr, func, arg, vid);
481 484 }
482 485
483 486 void
484 487 svp_remote_vl3_lookup(svp_t *svp, svp_query_t *sqp,
485 488 const struct sockaddr *addr, void *arg)
486 489 {
487 490 svp_remote_t *srp = svp->svp_remote;
488 491
489 492 sqp->sq_svp = svp;
490 493 svp_remote_vl3_common(srp, sqp, addr, svp_remote_vl3_lookup_cb,
491 494 arg, svp->svp_vid);
492 495 }
493 496
494 497 static void
495 498 svp_remote_log_request_cb(svp_query_t *sqp, void *arg)
496 499 {
497 500 svp_remote_t *srp = sqp->sq_arg;
498 501
499 502 assert(sqp->sq_wdata != NULL);
500 503 if (sqp->sq_status == SVP_S_OK)
501 504 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
502 505 sqp->sq_size);
503 506 else
504 507 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0);
505 508 }
506 509
507 510 void
508 511 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
509 512 size_t buflen)
510 513 {
511 514 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
512 515 boolean_t queued;
513 516
514 517 sqp->sq_func = svp_remote_log_request_cb;
515 518 sqp->sq_state = SVP_QUERY_INIT;
516 519 sqp->sq_arg = srp;
517 520 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
518 521 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
519 522 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
520 523 sqp->sq_header.svp_id = id_alloc(svp_idspace);
521 524 if (sqp->sq_header.svp_id == (id_t)-1)
522 525 libvarpd_panic("failed to allcoate from svp_idspace: %d",
523 526 errno);
524 527 sqp->sq_header.svp_crc32 = htonl(0);
525 528 sqp->sq_rdata = logr;
526 529 sqp->sq_rsize = sizeof (svp_log_req_t);
527 530 sqp->sq_wdata = buf;
528 531 sqp->sq_wsize = buflen;
529 532
530 533 logr->svlr_count = htonl(buflen);
531 534 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
532 535
533 536 /*
534 537 * If this fails, there isn't much that we can't do. Give the callback
535 538 * with a fatal status.
536 539 */
537 540 mutex_enter(&srp->sr_lock);
538 541 queued = svp_remote_conn_queue(srp, sqp);
539 542 mutex_exit(&srp->sr_lock);
540 543
541 544 if (queued == B_FALSE)
542 545 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
543 546 }
544 547
545 548 static void
546 549 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
547 550 {
548 551 svp_remote_t *srp = arg;
549 552
550 553 svp_shootdown_lrm_cb(srp, sqp->sq_status);
551 554 }
552 555
553 556 void
554 557 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
555 558 size_t buflen)
556 559 {
557 560 boolean_t queued;
558 561 svp_lrm_req_t *svrr = buf;
559 562
560 563 sqp->sq_func = svp_remote_lrm_request_cb;
561 564 sqp->sq_state = SVP_QUERY_INIT;
562 565 sqp->sq_arg = srp;
563 566 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
564 567 sqp->sq_header.svp_op = htons(SVP_R_LOG_RM);
565 568 sqp->sq_header.svp_size = htonl(buflen);
566 569 sqp->sq_header.svp_id = id_alloc(svp_idspace);
567 570 if (sqp->sq_header.svp_id == (id_t)-1)
568 571 libvarpd_panic("failed to allcoate from svp_idspace: %d",
569 572 errno);
570 573 sqp->sq_header.svp_crc32 = htonl(0);
571 574 sqp->sq_rdata = buf;
572 575 sqp->sq_rsize = buflen;
573 576 sqp->sq_wdata = NULL;
574 577 sqp->sq_wsize = 0;
575 578
576 579 /*
577 580 * We need to fix up the count to be in proper network order.
578 581 */
579 582 svrr->svrr_count = htonl(svrr->svrr_count);
580 583
581 584 /*
582 585 * If this fails, there isn't much that we can't do. Give the callback
583 586 * with a fatal status.
584 587 */
585 588 mutex_enter(&srp->sr_lock);
586 589 queued = svp_remote_conn_queue(srp, sqp);
587 590 mutex_exit(&srp->sr_lock);
588 591
589 592 if (queued == B_FALSE)
590 593 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
591 594 }
592 595
593 596 /* ARGSUSED */
594 597 void
595 598 svp_remote_dns_timer(void *unused)
596 599 {
597 600 svp_remote_t *s;
598 601 mutex_enter(&svp_remote_lock);
599 602 for (s = avl_first(&svp_remote_tree); s != NULL;
600 603 s = AVL_NEXT(&svp_remote_tree, s)) {
601 604 svp_host_queue(s);
602 605 }
603 606 mutex_exit(&svp_remote_lock);
604 607 }
605 608
606 609 void
607 610 svp_remote_resolved(svp_remote_t *srp, struct addrinfo *newaddrs)
608 611 {
609 612 struct addrinfo *a;
610 613 svp_conn_t *scp;
611 614 int ngen;
612 615
613 616 mutex_enter(&srp->sr_lock);
614 617 srp->sr_gen++;
615 618 ngen = srp->sr_gen;
616 619 mutex_exit(&srp->sr_lock);
617 620
618 621 for (a = newaddrs; a != NULL; a = a->ai_next) {
619 622 struct in6_addr in6;
620 623 struct in6_addr *addrp;
621 624
622 625 if (a->ai_family != AF_INET && a->ai_family != AF_INET6)
623 626 continue;
624 627
625 628 if (a->ai_family == AF_INET) {
626 629 struct sockaddr_in *v4;
627 630 v4 = (struct sockaddr_in *)a->ai_addr;
628 631 addrp = &in6;
629 632 IN6_INADDR_TO_V4MAPPED(&v4->sin_addr, addrp);
630 633 } else {
631 634 struct sockaddr_in6 *v6;
632 635 v6 = (struct sockaddr_in6 *)a->ai_addr;
633 636 addrp = &v6->sin6_addr;
634 637 }
635 638
636 639 mutex_enter(&srp->sr_lock);
637 640 for (scp = list_head(&srp->sr_conns); scp != NULL;
638 641 scp = list_next(&srp->sr_conns, scp)) {
639 642 mutex_enter(&scp->sc_lock);
640 643 if (bcmp(addrp, &scp->sc_addr,
641 644 sizeof (struct in6_addr)) == 0) {
642 645 scp->sc_gen = ngen;
643 646 mutex_exit(&scp->sc_lock);
644 647 break;
645 648 }
646 649 mutex_exit(&scp->sc_lock);
647 650 }
648 651
649 652 /*
650 653 * We need to be careful in the assumptions that we make here,
651 654 * as there's a good chance that svp_conn_create will
652 655 * drop the svp_remote_t`sr_lock to kick off its effective event
653 656 * loop.
654 657 */
655 658 if (scp == NULL)
656 659 (void) svp_conn_create(srp, addrp);
657 660 mutex_exit(&srp->sr_lock);
658 661 }
659 662
660 663 /*
661 664 * Now it's time to clean things up. We do not actively clean up the
662 665 * current connections that we have, instead allowing them to stay
663 666 * around assuming that they're still useful. Instead, we go through and
664 667 * purge the degraded list for anything that's from an older generation.
665 668 */
666 669 mutex_enter(&srp->sr_lock);
667 670 for (scp = list_head(&srp->sr_conns); scp != NULL;
668 671 scp = list_next(&srp->sr_conns, scp)) {
669 672 boolean_t fall = B_FALSE;
670 673 mutex_enter(&scp->sc_lock);
671 674 if (scp->sc_gen < srp->sr_gen)
672 675 fall = B_TRUE;
673 676 mutex_exit(&scp->sc_lock);
674 677 if (fall == B_TRUE)
675 678 svp_conn_fallout(scp);
676 679 }
677 680 mutex_exit(&srp->sr_lock);
678 681 }
679 682
680 683 /*
681 684 * This connection is in the process of being reset, we need to reassign all of
682 685 * its queries to other places or mark them as fatal. Note that the first
683 686 * connection was the one in flight when this failed. We always mark it as
684 687 * failed to avoid trying to reset its state.
685 688 */
686 689 void
687 690 svp_remote_reassign(svp_remote_t *srp, svp_conn_t *scp)
688 691 {
689 692 boolean_t first = B_TRUE;
690 693 assert(MUTEX_HELD(&srp->sr_lock));
691 694 assert(MUTEX_HELD(&srp->sr_lock));
692 695 svp_query_t *sqp;
693 696
694 697 /*
695 698 * As we try to reassigning all of its queries, remove it from the list.
696 699 */
697 700 list_remove(&srp->sr_conns, scp);
698 701
699 702 while ((sqp = list_remove_head(&scp->sc_queries)) != NULL) {
700 703
701 704 if (first == B_TRUE) {
702 705 sqp->sq_status = SVP_S_FATAL;
703 706 sqp->sq_func(sqp, sqp->sq_arg);
704 707 continue;
705 708 }
706 709
707 710 sqp->sq_acttime = -1;
708 711
709 712 /*
710 713 * We may want to maintain a queue of these for some time rather
711 714 * than just failing them all.
712 715 */
713 716 if (svp_remote_conn_queue(srp, sqp) == B_FALSE) {
714 717 sqp->sq_status = SVP_S_FATAL;
715 718 sqp->sq_func(sqp, sqp->sq_arg);
716 719 }
717 720 }
718 721
719 722 /*
720 723 * Now that we're done, go ahead and re-insert.
721 724 */
722 725 list_insert_tail(&srp->sr_conns, scp);
723 726 }
724 727
725 728 void
726 729 svp_remote_degrade(svp_remote_t *srp, svp_degrade_state_t flag)
727 730 {
728 731 int sf, nf;
729 732 char buf[256];
730 733
731 734 assert(MUTEX_HELD(&srp->sr_lock));
732 735
733 736 if (flag == SVP_RD_ALL || flag == 0)
734 737 libvarpd_panic("invalid flag passed to degrade");
735 738
736 739 if ((flag & srp->sr_degrade) != 0) {
737 740 return;
738 741 }
739 742
740 743 sf = ffs(srp->sr_degrade);
741 744 nf = ffs(flag);
742 745 srp->sr_degrade |= flag;
743 746 if (sf == 0 || sf > nf) {
744 747 svp_t *svp;
745 748 svp_remote_mkfmamsg(srp, flag, buf, sizeof (buf));
746 749
747 750 for (svp = avl_first(&srp->sr_tree); svp != NULL;
748 751 svp = AVL_NEXT(&srp->sr_tree, svp)) {
749 752 libvarpd_fma_degrade(svp->svp_hdl, buf);
750 753 }
751 754 }
752 755 }
753 756
754 757 void
755 758 svp_remote_restore(svp_remote_t *srp, svp_degrade_state_t flag)
756 759 {
757 760 int sf, nf;
758 761
759 762 assert(MUTEX_HELD(&srp->sr_lock));
760 763 sf = ffs(srp->sr_degrade);
761 764 if ((srp->sr_degrade & flag) != flag)
762 765 return;
763 766 srp->sr_degrade &= ~flag;
764 767 nf = ffs(srp->sr_degrade);
765 768
766 769 /*
767 770 * If we're now empty, restore the device. If we still are degraded, but
768 771 * we now have a higher base than we used to, change the message.
769 772 */
770 773 if (srp->sr_degrade == 0) {
771 774 svp_t *svp;
772 775 for (svp = avl_first(&srp->sr_tree); svp != NULL;
773 776 svp = AVL_NEXT(&srp->sr_tree, svp)) {
774 777 libvarpd_fma_restore(svp->svp_hdl);
775 778 }
776 779 } else if (nf != sf) {
777 780 svp_t *svp;
778 781 char buf[256];
779 782
780 783 svp_remote_mkfmamsg(srp, 1U << (nf - 1), buf, sizeof (buf));
781 784 for (svp = avl_first(&srp->sr_tree); svp != NULL;
782 785 svp = AVL_NEXT(&srp->sr_tree, svp)) {
783 786 libvarpd_fma_degrade(svp->svp_hdl, buf);
784 787 }
785 788 }
786 789 }
787 790
788 791 void
789 792 svp_remote_shootdown_vl3_cb(svp_query_t *sqp, void *arg)
790 793 {
791 794 svp_shoot_vl3_t *squery = arg;
792 795 svp_log_vl3_t *svl3 = squery->ssv_vl3;
793 796 svp_sdlog_t *sdl = squery->ssv_log;
794 797
795 798 if (sqp->sq_status == SVP_S_OK) {
796 799 svp_t *svp, lookup;
797 800
798 801 svp_remote_t *srp = sdl->sdl_remote;
799 802 svp_vl3_ack_t *vl3a = (svp_vl3_ack_t *)sqp->sq_wdata;
800 803
801 804 lookup.svp_vid = ntohl(svl3->svl3_vnetid);
802 805 mutex_enter(&srp->sr_lock);
803 806 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
804 807 svp->svp_cb.scb_vl3_inject(svp, ntohs(svl3->svl3_vlan),
805 808 (struct in6_addr *)svl3->svl3_ip, vl3a->sl3a_mac,
806 809 NULL);
807 810 }
808 811 mutex_exit(&srp->sr_lock);
809 812
810 813 }
811 814
812 815 svp_shootdown_vl3_cb(sqp->sq_status, svl3, sdl);
813 816
814 817 umem_free(squery, sizeof (svp_shoot_vl3_t));
815 818 }
816 819
817 820 void
818 821 svp_remote_shootdown_vl3(svp_remote_t *srp, svp_log_vl3_t *svl3,
819 822 svp_sdlog_t *sdl)
820 823 {
821 824 svp_shoot_vl3_t *squery;
822 825
823 826 squery = umem_zalloc(sizeof (svp_shoot_vl3_t), UMEM_DEFAULT);
824 827 if (squery == NULL) {
825 828 svp_shootdown_vl3_cb(SVP_S_FATAL, svl3, sdl);
826 829 return;
827 830 }
828 831
829 832 squery->ssv_vl3 = svl3;
830 833 squery->ssv_log = sdl;
831 834 squery->ssv_sock.sin6_family = AF_INET6;
832 835 bcopy(svl3->svl3_ip, &squery->ssv_sock.sin6_addr,
833 836 sizeof (svl3->svl3_ip));
834 837 svp_remote_vl3_logreq(srp, &squery->ssv_query, ntohl(svl3->svl3_vnetid),
835 838 (struct sockaddr *)&squery->ssv_sock, svp_remote_shootdown_vl3_cb,
836 839 squery);
837 840 }
838 841
839 842 void
840 843 svp_remote_shootdown_vl2(svp_remote_t *srp, svp_log_vl2_t *svl2)
841 844 {
842 845 svp_t *svp, lookup;
843 846
844 847 lookup.svp_vid = ntohl(svl2->svl2_vnetid);
845 848 mutex_enter(&srp->sr_lock);
846 849 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
847 850 svp->svp_cb.scb_vl2_invalidate(svp, svl2->svl2_mac);
848 851 }
849 852 mutex_exit(&srp->sr_lock);
850 853 }
851 854
852 855 int
853 856 svp_remote_init(void)
854 857 {
855 858 svp_idspace = id_space_create("svp_req_ids", 1, INT32_MAX);
856 859 if (svp_idspace == NULL)
857 860 return (errno);
858 861 avl_create(&svp_remote_tree, svp_remote_comparator,
859 862 sizeof (svp_remote_t), offsetof(svp_remote_t, sr_gnode));
860 863 svp_dns_timer.st_func = svp_remote_dns_timer;
861 864 svp_dns_timer.st_arg = NULL;
862 865 svp_dns_timer.st_oneshot = B_FALSE;
863 866 svp_dns_timer.st_value = svp_dns_timer_rate;
864 867 svp_timer_add(&svp_dns_timer);
865 868 return (0);
866 869 }
867 870
868 871 void
869 872 svp_remote_fini(void)
870 873 {
871 874 svp_timer_remove(&svp_dns_timer);
872 875 avl_destroy(&svp_remote_tree);
873 876 if (svp_idspace == NULL)
874 877 id_space_destroy(svp_idspace);
875 878 }
|
↓ open down ↓ |
467 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX