Print this page
Version bump SVP to 2
| 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 /*
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 248 if (svp->svp_cb.scb_route_lookup == NULL)
249 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);
|
↓ open down ↓ |
271 lines elided |
↑ open up ↑ |
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 - * Walk the list of connections and find the first one that's available, the
283 - * move it to the back of the list so it's less likely to be used again.
282 + * See if the request can be sent over the connection's supported version.
283 + * Scribble the version in the request itself. NOTE that we do not check the
284 + * version that already exists in sqp->sq_header.svp_ver, as we may be called
285 + * from svp_remote_reassign() (and change versions when arriving at a new
286 + * connection).
284 287 */
285 288 static boolean_t
289 +svp_outbound_version_check(int version, svp_query_t *sqp)
290 +{
291 + uint16_t op = htons(sqp->sq_header.svp_op);
292 +
293 + /*
294 + * As of v1 -> v2, we really only need to restrict SVP_R_ROUTE_REQ
295 + * as v2-only. Reflect that here.
296 + *
297 + * NOTE that if any message semantics change between future versions,
298 + * (e.g. "in v3 SVP_R_VL2_REQ takes on additional work"), we'll
299 + * need to more-deeply inspect the query. It's possible that the
300 + * svp_op space is big enough to just continue op-only inspections.
301 + */
302 +
303 + assert(version > 0 && version <= SVP_CURRENT_VERSION);
304 +
305 + if (op != SVP_R_ROUTE_REQ || version >= SVP_VERSION_TWO) {
306 + sqp->sq_header.svp_ver = htons(version);
307 + return (B_TRUE);
308 + }
309 + return (B_FALSE);
310 +}
311 +
312 +/*
313 + * Walk the list of connections and find the first one that's available AND
314 + * version-appropriate for the message, then move the matched connection to
315 + * the back of the list so it's less likely to be used again.
316 + */
317 +static boolean_t
286 318 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
287 319 {
288 320 svp_conn_t *scp;
289 321
290 322 assert(MUTEX_HELD(&srp->sr_lock));
291 323 for (scp = list_head(&srp->sr_conns); scp != NULL;
292 324 scp = list_next(&srp->sr_conns, scp)) {
293 325 mutex_enter(&scp->sc_lock);
294 - if (scp->sc_cstate != SVP_CS_ACTIVE) {
326 + if (scp->sc_cstate != SVP_CS_ACTIVE ||
327 + !svp_outbound_version_check(scp->sc_version, sqp)) {
295 328 mutex_exit(&scp->sc_lock);
296 329 continue;
297 330 }
298 331 svp_conn_queue(scp, sqp);
299 332 mutex_exit(&scp->sc_lock);
300 333 list_remove(&srp->sr_conns, scp);
301 334 list_insert_tail(&srp->sr_conns, scp);
302 335 return (B_TRUE);
303 336 }
304 337
305 338 return (B_FALSE);
306 339 }
307 340
308 341 static void
309 342 svp_remote_vl2_lookup_cb(svp_query_t *sqp, void *arg)
310 343 {
311 344 svp_t *svp = sqp->sq_svp;
312 345 svp_vl2_ack_t *vl2a = (svp_vl2_ack_t *)sqp->sq_wdata;
313 346
314 347 if (sqp->sq_status == SVP_S_OK)
315 348 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status,
316 349 (struct in6_addr *)vl2a->sl2a_addr, ntohs(vl2a->sl2a_port),
317 350 arg);
318 351 else
319 352 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status, NULL, 0, arg);
320 353 }
321 354
322 355 void
323 356 svp_remote_vl2_lookup(svp_t *svp, svp_query_t *sqp, const uint8_t *mac,
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
324 357 void *arg)
325 358 {
326 359 svp_remote_t *srp;
327 360 svp_vl2_req_t *vl2r = &sqp->sq_rdun.sqd_vl2r;
328 361
329 362 srp = svp->svp_remote;
330 363 sqp->sq_func = svp_remote_vl2_lookup_cb;
331 364 sqp->sq_arg = arg;
332 365 sqp->sq_svp = svp;
333 366 sqp->sq_state = SVP_QUERY_INIT;
334 - sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
335 367 sqp->sq_header.svp_op = htons(SVP_R_VL2_REQ);
336 368 sqp->sq_header.svp_size = htonl(sizeof (svp_vl2_req_t));
337 369 sqp->sq_header.svp_id = id_alloc(svp_idspace);
338 370 if (sqp->sq_header.svp_id == (id_t)-1)
339 371 libvarpd_panic("failed to allcoate from svp_idspace: %d",
340 372 errno);
341 373 sqp->sq_header.svp_crc32 = htonl(0);
342 374 sqp->sq_rdata = vl2r;
343 375 sqp->sq_rsize = sizeof (svp_vl2_req_t);
344 376 sqp->sq_wdata = NULL;
345 377 sqp->sq_wsize = 0;
346 378
347 379 bcopy(mac, vl2r->sl2r_mac, ETHERADDRL);
348 380 vl2r->sl2r_vnetid = ntohl(svp->svp_vid);
349 381
350 382 mutex_enter(&srp->sr_lock);
351 383 if (svp_remote_conn_queue(srp, sqp) == B_FALSE)
352 384 svp->svp_cb.scb_vl2_lookup(svp, SVP_S_FATAL, NULL, NULL, arg);
353 385 mutex_exit(&srp->sr_lock);
354 386 }
355 387
356 388 static void
357 389 svp_remote_route_lookup_cb(svp_query_t *sqp, void *arg)
358 390 {
359 391 svp_t *svp = sqp->sq_svp;
360 392 svp_route_ack_t *sra = (svp_route_ack_t *)sqp->sq_wdata;
361 393
362 394 if (sqp->sq_status == SVP_S_OK) {
363 395 svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
364 396 sra->sra_dcid, sra->sra_vnetid, sra->sra_vlan,
365 397 sra->sra_srcmac, sra->sra_dstmac, sra->sra_port,
366 398 sra->sra_ip, sra->sra_src_pfx, sra->sra_dst_pfx, arg);
367 399 } else {
368 400 svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
369 401 0, 0, 0, NULL, NULL, 0, NULL, 0, 0, arg);
370 402 }
371 403 }
372 404
373 405 void
374 406 svp_remote_route_lookup(svp_t *svp, svp_query_t *sqp,
375 407 const struct in6_addr *src, const struct in6_addr *dst, uint32_t vnetid,
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
376 408 uint16_t vlan, void *arg)
377 409 {
378 410 svp_remote_t *srp;
379 411 svp_route_req_t *srr = &sqp->sq_rdun.sqd_rr;
380 412
381 413 srp = svp->svp_remote;
382 414 sqp->sq_func = svp_remote_route_lookup_cb;
383 415 sqp->sq_arg = arg;
384 416 sqp->sq_svp = svp;
385 417 sqp->sq_state = SVP_QUERY_INIT;
386 - sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
387 418 sqp->sq_header.svp_op = htons(SVP_R_ROUTE_REQ);
388 419 sqp->sq_header.svp_size = htonl(sizeof (svp_route_req_t));
389 420 sqp->sq_header.svp_id = id_alloc(svp_idspace);
390 421 if (sqp->sq_header.svp_id == (id_t)-1)
391 422 libvarpd_panic("failed to allcoate from svp_idspace: %d",
392 423 errno);
393 424 sqp->sq_header.svp_crc32 = htonl(0);
394 425 sqp->sq_rdata = srr;
395 426
396 427 bcopy(src, srr->srr_srcip, sizeof (struct in6_addr));
397 428 bcopy(dst, srr->srr_dstip, sizeof (struct in6_addr));
398 429 /* Caller should've checked both are the same type... */
399 430 srr->srr_vnetid = vnetid;
400 431 srr->srr_vlan = vlan;
401 432 srr->srr_pad = 0;
402 433
403 434 mutex_enter(&srp->sr_lock);
404 435 if (!svp_remote_conn_queue(srp, sqp)) {
405 436 sqp->sq_status = SVP_S_FATAL;
406 437 sqp->sq_func(sqp, arg);
407 438 }
408 439 mutex_exit(&srp->sr_lock);
409 440 }
410 441
411 442 static void
412 443 svp_remote_vl3_lookup_cb(svp_query_t *sqp, void *arg)
413 444 {
414 445 svp_t *svp = sqp->sq_svp;
415 446 svp_vl3_ack_t *vl3a = (svp_vl3_ack_t *)sqp->sq_wdata;
416 447
417 448 if (sqp->sq_status == SVP_S_OK)
418 449 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, vl3a->sl3a_mac,
419 450 (struct in6_addr *)vl3a->sl3a_uip, ntohs(vl3a->sl3a_uport),
420 451 arg);
421 452 else
422 453 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, NULL, NULL, 0,
423 454 arg);
424 455 }
425 456
426 457 static void
427 458 svp_remote_vl3_common(svp_remote_t *srp, svp_query_t *sqp,
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
428 459 const struct sockaddr *addr, svp_query_f func, void *arg, uint32_t vid)
429 460 {
430 461 svp_vl3_req_t *vl3r = &sqp->sq_rdun.sdq_vl3r;
431 462
432 463 if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
433 464 libvarpd_panic("unexpected sa_family for the vl3 lookup");
434 465
435 466 sqp->sq_func = func;
436 467 sqp->sq_arg = arg;
437 468 sqp->sq_state = SVP_QUERY_INIT;
438 - sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
439 469 sqp->sq_header.svp_op = htons(SVP_R_VL3_REQ);
440 470 sqp->sq_header.svp_size = htonl(sizeof (svp_vl3_req_t));
441 471 sqp->sq_header.svp_id = id_alloc(svp_idspace);
442 472 if (sqp->sq_header.svp_id == (id_t)-1)
443 473 libvarpd_panic("failed to allcoate from svp_idspace: %d",
444 474 errno);
445 475 sqp->sq_header.svp_crc32 = htonl(0);
446 476 sqp->sq_rdata = vl3r;
447 477 sqp->sq_rsize = sizeof (svp_vl3_req_t);
448 478 sqp->sq_wdata = NULL;
449 479 sqp->sq_wsize = 0;
450 480
451 481 if (addr->sa_family == AF_INET6) {
452 482 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)addr;
453 483 vl3r->sl3r_type = htonl(SVP_VL3_IPV6);
454 484 bcopy(&s6->sin6_addr, vl3r->sl3r_ip,
455 485 sizeof (struct in6_addr));
456 486 } else {
457 487 struct sockaddr_in *s4 = (struct sockaddr_in *)addr;
458 488 struct in6_addr v6;
459 489
460 490 vl3r->sl3r_type = htonl(SVP_VL3_IP);
461 491 IN6_INADDR_TO_V4MAPPED(&s4->sin_addr, &v6);
462 492 bcopy(&v6, vl3r->sl3r_ip, sizeof (struct in6_addr));
463 493 }
464 494 vl3r->sl3r_vnetid = htonl(vid);
465 495
466 496 mutex_enter(&srp->sr_lock);
467 497 if (svp_remote_conn_queue(srp, sqp) == B_FALSE) {
468 498 sqp->sq_status = SVP_S_FATAL;
469 499 sqp->sq_func(sqp, arg);
470 500 }
471 501 mutex_exit(&srp->sr_lock);
472 502 }
473 503
474 504 /*
475 505 * This is a request to do a VL3 look-up that originated internally as opposed
476 506 * to coming from varpd. As such we need a slightly different query callback
477 507 * function upon completion and don't go through the normal path with the svp_t.
478 508 */
479 509 void
480 510 svp_remote_vl3_logreq(svp_remote_t *srp, svp_query_t *sqp, uint32_t vid,
481 511 const struct sockaddr *addr, svp_query_f func, void *arg)
482 512 {
483 513 svp_remote_vl3_common(srp, sqp, addr, func, arg, vid);
484 514 }
485 515
486 516 void
487 517 svp_remote_vl3_lookup(svp_t *svp, svp_query_t *sqp,
488 518 const struct sockaddr *addr, void *arg)
489 519 {
490 520 svp_remote_t *srp = svp->svp_remote;
491 521
492 522 sqp->sq_svp = svp;
493 523 svp_remote_vl3_common(srp, sqp, addr, svp_remote_vl3_lookup_cb,
494 524 arg, svp->svp_vid);
495 525 }
496 526
497 527 static void
498 528 svp_remote_log_request_cb(svp_query_t *sqp, void *arg)
499 529 {
500 530 svp_remote_t *srp = sqp->sq_arg;
501 531
502 532 assert(sqp->sq_wdata != NULL);
503 533 if (sqp->sq_status == SVP_S_OK)
504 534 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
505 535 sqp->sq_size);
506 536 else
507 537 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0);
508 538 }
509 539
|
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
510 540 void
511 541 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
512 542 size_t buflen)
513 543 {
514 544 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
515 545 boolean_t queued;
516 546
517 547 sqp->sq_func = svp_remote_log_request_cb;
518 548 sqp->sq_state = SVP_QUERY_INIT;
519 549 sqp->sq_arg = srp;
520 - sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
521 550 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
522 551 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
523 552 sqp->sq_header.svp_id = id_alloc(svp_idspace);
524 553 if (sqp->sq_header.svp_id == (id_t)-1)
525 554 libvarpd_panic("failed to allcoate from svp_idspace: %d",
526 555 errno);
527 556 sqp->sq_header.svp_crc32 = htonl(0);
528 557 sqp->sq_rdata = logr;
529 558 sqp->sq_rsize = sizeof (svp_log_req_t);
530 559 sqp->sq_wdata = buf;
531 560 sqp->sq_wsize = buflen;
532 561
533 562 logr->svlr_count = htonl(buflen);
534 563 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
535 564
536 565 /*
537 566 * If this fails, there isn't much that we can't do. Give the callback
538 567 * with a fatal status.
539 568 */
540 569 mutex_enter(&srp->sr_lock);
541 570 queued = svp_remote_conn_queue(srp, sqp);
542 571 mutex_exit(&srp->sr_lock);
543 572
544 573 if (queued == B_FALSE)
545 574 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
546 575 }
547 576
548 577 static void
549 578 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
550 579 {
551 580 svp_remote_t *srp = arg;
552 581
553 582 svp_shootdown_lrm_cb(srp, sqp->sq_status);
554 583 }
555 584
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
556 585 void
557 586 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
558 587 size_t buflen)
559 588 {
560 589 boolean_t queued;
561 590 svp_lrm_req_t *svrr = buf;
562 591
563 592 sqp->sq_func = svp_remote_lrm_request_cb;
564 593 sqp->sq_state = SVP_QUERY_INIT;
565 594 sqp->sq_arg = srp;
566 - sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
567 595 sqp->sq_header.svp_op = htons(SVP_R_LOG_RM);
568 596 sqp->sq_header.svp_size = htonl(buflen);
569 597 sqp->sq_header.svp_id = id_alloc(svp_idspace);
570 598 if (sqp->sq_header.svp_id == (id_t)-1)
571 599 libvarpd_panic("failed to allcoate from svp_idspace: %d",
572 600 errno);
573 601 sqp->sq_header.svp_crc32 = htonl(0);
574 602 sqp->sq_rdata = buf;
575 603 sqp->sq_rsize = buflen;
576 604 sqp->sq_wdata = NULL;
577 605 sqp->sq_wsize = 0;
578 606
579 607 /*
580 608 * We need to fix up the count to be in proper network order.
581 609 */
582 610 svrr->svrr_count = htonl(svrr->svrr_count);
583 611
584 612 /*
585 613 * If this fails, there isn't much that we can't do. Give the callback
586 614 * with a fatal status.
587 615 */
588 616 mutex_enter(&srp->sr_lock);
589 617 queued = svp_remote_conn_queue(srp, sqp);
590 618 mutex_exit(&srp->sr_lock);
591 619
592 620 if (queued == B_FALSE)
593 621 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
594 622 }
595 623
596 624 /* ARGSUSED */
597 625 void
598 626 svp_remote_dns_timer(void *unused)
599 627 {
600 628 svp_remote_t *s;
601 629 mutex_enter(&svp_remote_lock);
602 630 for (s = avl_first(&svp_remote_tree); s != NULL;
603 631 s = AVL_NEXT(&svp_remote_tree, s)) {
604 632 svp_host_queue(s);
605 633 }
606 634 mutex_exit(&svp_remote_lock);
607 635 }
608 636
609 637 void
610 638 svp_remote_resolved(svp_remote_t *srp, struct addrinfo *newaddrs)
611 639 {
612 640 struct addrinfo *a;
613 641 svp_conn_t *scp;
614 642 int ngen;
615 643
616 644 mutex_enter(&srp->sr_lock);
617 645 srp->sr_gen++;
618 646 ngen = srp->sr_gen;
619 647 mutex_exit(&srp->sr_lock);
620 648
621 649 for (a = newaddrs; a != NULL; a = a->ai_next) {
622 650 struct in6_addr in6;
623 651 struct in6_addr *addrp;
624 652
625 653 if (a->ai_family != AF_INET && a->ai_family != AF_INET6)
626 654 continue;
627 655
628 656 if (a->ai_family == AF_INET) {
629 657 struct sockaddr_in *v4;
630 658 v4 = (struct sockaddr_in *)a->ai_addr;
631 659 addrp = &in6;
632 660 IN6_INADDR_TO_V4MAPPED(&v4->sin_addr, addrp);
633 661 } else {
634 662 struct sockaddr_in6 *v6;
635 663 v6 = (struct sockaddr_in6 *)a->ai_addr;
636 664 addrp = &v6->sin6_addr;
637 665 }
638 666
639 667 mutex_enter(&srp->sr_lock);
640 668 for (scp = list_head(&srp->sr_conns); scp != NULL;
641 669 scp = list_next(&srp->sr_conns, scp)) {
642 670 mutex_enter(&scp->sc_lock);
643 671 if (bcmp(addrp, &scp->sc_addr,
644 672 sizeof (struct in6_addr)) == 0) {
645 673 scp->sc_gen = ngen;
646 674 mutex_exit(&scp->sc_lock);
647 675 break;
648 676 }
649 677 mutex_exit(&scp->sc_lock);
650 678 }
651 679
652 680 /*
653 681 * We need to be careful in the assumptions that we make here,
654 682 * as there's a good chance that svp_conn_create will
655 683 * drop the svp_remote_t`sr_lock to kick off its effective event
656 684 * loop.
657 685 */
658 686 if (scp == NULL)
659 687 (void) svp_conn_create(srp, addrp);
660 688 mutex_exit(&srp->sr_lock);
661 689 }
662 690
663 691 /*
664 692 * Now it's time to clean things up. We do not actively clean up the
665 693 * current connections that we have, instead allowing them to stay
666 694 * around assuming that they're still useful. Instead, we go through and
667 695 * purge the degraded list for anything that's from an older generation.
668 696 */
669 697 mutex_enter(&srp->sr_lock);
670 698 for (scp = list_head(&srp->sr_conns); scp != NULL;
671 699 scp = list_next(&srp->sr_conns, scp)) {
672 700 boolean_t fall = B_FALSE;
673 701 mutex_enter(&scp->sc_lock);
674 702 if (scp->sc_gen < srp->sr_gen)
675 703 fall = B_TRUE;
676 704 mutex_exit(&scp->sc_lock);
677 705 if (fall == B_TRUE)
678 706 svp_conn_fallout(scp);
679 707 }
680 708 mutex_exit(&srp->sr_lock);
681 709 }
682 710
683 711 /*
684 712 * This connection is in the process of being reset, we need to reassign all of
685 713 * its queries to other places or mark them as fatal. Note that the first
686 714 * connection was the one in flight when this failed. We always mark it as
687 715 * failed to avoid trying to reset its state.
688 716 */
689 717 void
690 718 svp_remote_reassign(svp_remote_t *srp, svp_conn_t *scp)
691 719 {
692 720 boolean_t first = B_TRUE;
693 721 assert(MUTEX_HELD(&srp->sr_lock));
694 722 assert(MUTEX_HELD(&srp->sr_lock));
695 723 svp_query_t *sqp;
696 724
697 725 /*
698 726 * As we try to reassigning all of its queries, remove it from the list.
699 727 */
700 728 list_remove(&srp->sr_conns, scp);
701 729
702 730 while ((sqp = list_remove_head(&scp->sc_queries)) != NULL) {
703 731
704 732 if (first == B_TRUE) {
705 733 sqp->sq_status = SVP_S_FATAL;
706 734 sqp->sq_func(sqp, sqp->sq_arg);
707 735 continue;
708 736 }
709 737
710 738 sqp->sq_acttime = -1;
711 739
712 740 /*
713 741 * We may want to maintain a queue of these for some time rather
714 742 * than just failing them all.
715 743 */
716 744 if (svp_remote_conn_queue(srp, sqp) == B_FALSE) {
717 745 sqp->sq_status = SVP_S_FATAL;
718 746 sqp->sq_func(sqp, sqp->sq_arg);
719 747 }
720 748 }
721 749
722 750 /*
723 751 * Now that we're done, go ahead and re-insert.
724 752 */
725 753 list_insert_tail(&srp->sr_conns, scp);
726 754 }
727 755
728 756 void
729 757 svp_remote_degrade(svp_remote_t *srp, svp_degrade_state_t flag)
730 758 {
731 759 int sf, nf;
732 760 char buf[256];
733 761
734 762 assert(MUTEX_HELD(&srp->sr_lock));
735 763
736 764 if (flag == SVP_RD_ALL || flag == 0)
737 765 libvarpd_panic("invalid flag passed to degrade");
738 766
739 767 if ((flag & srp->sr_degrade) != 0) {
740 768 return;
741 769 }
742 770
743 771 sf = ffs(srp->sr_degrade);
744 772 nf = ffs(flag);
745 773 srp->sr_degrade |= flag;
746 774 if (sf == 0 || sf > nf) {
747 775 svp_t *svp;
748 776 svp_remote_mkfmamsg(srp, flag, buf, sizeof (buf));
749 777
750 778 for (svp = avl_first(&srp->sr_tree); svp != NULL;
751 779 svp = AVL_NEXT(&srp->sr_tree, svp)) {
752 780 libvarpd_fma_degrade(svp->svp_hdl, buf);
753 781 }
754 782 }
755 783 }
756 784
757 785 void
758 786 svp_remote_restore(svp_remote_t *srp, svp_degrade_state_t flag)
759 787 {
760 788 int sf, nf;
761 789
762 790 assert(MUTEX_HELD(&srp->sr_lock));
763 791 sf = ffs(srp->sr_degrade);
764 792 if ((srp->sr_degrade & flag) != flag)
765 793 return;
766 794 srp->sr_degrade &= ~flag;
767 795 nf = ffs(srp->sr_degrade);
768 796
769 797 /*
770 798 * If we're now empty, restore the device. If we still are degraded, but
771 799 * we now have a higher base than we used to, change the message.
772 800 */
773 801 if (srp->sr_degrade == 0) {
774 802 svp_t *svp;
775 803 for (svp = avl_first(&srp->sr_tree); svp != NULL;
776 804 svp = AVL_NEXT(&srp->sr_tree, svp)) {
777 805 libvarpd_fma_restore(svp->svp_hdl);
778 806 }
779 807 } else if (nf != sf) {
780 808 svp_t *svp;
781 809 char buf[256];
782 810
783 811 svp_remote_mkfmamsg(srp, 1U << (nf - 1), buf, sizeof (buf));
784 812 for (svp = avl_first(&srp->sr_tree); svp != NULL;
785 813 svp = AVL_NEXT(&srp->sr_tree, svp)) {
786 814 libvarpd_fma_degrade(svp->svp_hdl, buf);
787 815 }
788 816 }
789 817 }
790 818
791 819 void
792 820 svp_remote_shootdown_vl3_cb(svp_query_t *sqp, void *arg)
793 821 {
794 822 svp_shoot_vl3_t *squery = arg;
795 823 svp_log_vl3_t *svl3 = squery->ssv_vl3;
796 824 svp_sdlog_t *sdl = squery->ssv_log;
797 825
798 826 if (sqp->sq_status == SVP_S_OK) {
799 827 svp_t *svp, lookup;
800 828
801 829 svp_remote_t *srp = sdl->sdl_remote;
802 830 svp_vl3_ack_t *vl3a = (svp_vl3_ack_t *)sqp->sq_wdata;
803 831
804 832 lookup.svp_vid = ntohl(svl3->svl3_vnetid);
805 833 mutex_enter(&srp->sr_lock);
806 834 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
807 835 svp->svp_cb.scb_vl3_inject(svp, ntohs(svl3->svl3_vlan),
808 836 (struct in6_addr *)svl3->svl3_ip, vl3a->sl3a_mac,
809 837 NULL);
810 838 }
811 839 mutex_exit(&srp->sr_lock);
812 840
813 841 }
814 842
815 843 svp_shootdown_vl3_cb(sqp->sq_status, svl3, sdl);
816 844
817 845 umem_free(squery, sizeof (svp_shoot_vl3_t));
818 846 }
819 847
820 848 void
821 849 svp_remote_shootdown_vl3(svp_remote_t *srp, svp_log_vl3_t *svl3,
822 850 svp_sdlog_t *sdl)
823 851 {
824 852 svp_shoot_vl3_t *squery;
825 853
826 854 squery = umem_zalloc(sizeof (svp_shoot_vl3_t), UMEM_DEFAULT);
827 855 if (squery == NULL) {
828 856 svp_shootdown_vl3_cb(SVP_S_FATAL, svl3, sdl);
829 857 return;
830 858 }
831 859
832 860 squery->ssv_vl3 = svl3;
833 861 squery->ssv_log = sdl;
834 862 squery->ssv_sock.sin6_family = AF_INET6;
835 863 bcopy(svl3->svl3_ip, &squery->ssv_sock.sin6_addr,
836 864 sizeof (svl3->svl3_ip));
837 865 svp_remote_vl3_logreq(srp, &squery->ssv_query, ntohl(svl3->svl3_vnetid),
838 866 (struct sockaddr *)&squery->ssv_sock, svp_remote_shootdown_vl3_cb,
839 867 squery);
840 868 }
841 869
842 870 void
843 871 svp_remote_shootdown_vl2(svp_remote_t *srp, svp_log_vl2_t *svl2)
844 872 {
845 873 svp_t *svp, lookup;
846 874
847 875 lookup.svp_vid = ntohl(svl2->svl2_vnetid);
848 876 mutex_enter(&srp->sr_lock);
849 877 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
850 878 svp->svp_cb.scb_vl2_invalidate(svp, svl2->svl2_mac);
851 879 }
852 880 mutex_exit(&srp->sr_lock);
853 881 }
854 882
855 883 int
856 884 svp_remote_init(void)
857 885 {
858 886 svp_idspace = id_space_create("svp_req_ids", 1, INT32_MAX);
859 887 if (svp_idspace == NULL)
860 888 return (errno);
861 889 avl_create(&svp_remote_tree, svp_remote_comparator,
862 890 sizeof (svp_remote_t), offsetof(svp_remote_t, sr_gnode));
863 891 svp_dns_timer.st_func = svp_remote_dns_timer;
864 892 svp_dns_timer.st_arg = NULL;
865 893 svp_dns_timer.st_oneshot = B_FALSE;
866 894 svp_dns_timer.st_value = svp_dns_timer_rate;
867 895 svp_timer_add(&svp_dns_timer);
868 896 return (0);
869 897 }
870 898
871 899 void
872 900 svp_remote_fini(void)
873 901 {
874 902 svp_timer_remove(&svp_dns_timer);
875 903 avl_destroy(&svp_remote_tree);
876 904 if (svp_idspace == NULL)
877 905 id_space_destroy(svp_idspace);
878 906 }
|
↓ open down ↓ |
302 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX