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