262 void
263 svp_remote_detach(svp_t *svp)
264 {
265 svp_t *lookup;
266 svp_remote_t *srp = svp->svp_remote;
267
268 if (srp == NULL)
269 libvarpd_panic("trying to detach remote when none exists");
270
271 mutex_enter(&srp->sr_lock);
272 lookup = avl_find(&srp->sr_tree, svp, NULL);
273 if (lookup == NULL || lookup != svp)
274 libvarpd_panic("inconsitent remote avl tree...");
275 avl_remove(&srp->sr_tree, svp);
276 svp->svp_remote = NULL;
277 mutex_exit(&srp->sr_lock);
278 svp_remote_release(srp);
279 }
280
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.
284 */
285 static boolean_t
286 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
287 {
288 svp_conn_t *scp;
289
290 assert(MUTEX_HELD(&srp->sr_lock));
291 for (scp = list_head(&srp->sr_conns); scp != NULL;
292 scp = list_next(&srp->sr_conns, scp)) {
293 mutex_enter(&scp->sc_lock);
294 if (scp->sc_cstate != SVP_CS_ACTIVE) {
295 mutex_exit(&scp->sc_lock);
296 continue;
297 }
298 svp_conn_queue(scp, sqp);
299 mutex_exit(&scp->sc_lock);
300 list_remove(&srp->sr_conns, scp);
301 list_insert_tail(&srp->sr_conns, scp);
302 return (B_TRUE);
303 }
304
305 return (B_FALSE);
306 }
307
308 static void
309 svp_remote_vl2_lookup_cb(svp_query_t *sqp, void *arg)
310 {
311 svp_t *svp = sqp->sq_svp;
312 svp_vl2_ack_t *vl2a = (svp_vl2_ack_t *)sqp->sq_wdata;
313
314 if (sqp->sq_status == SVP_S_OK)
315 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status,
316 (struct in6_addr *)vl2a->sl2a_addr, ntohs(vl2a->sl2a_port),
317 arg);
318 else
319 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status, NULL, 0, arg);
320 }
321
322 void
323 svp_remote_vl2_lookup(svp_t *svp, svp_query_t *sqp, const uint8_t *mac,
324 void *arg)
325 {
326 svp_remote_t *srp;
327 svp_vl2_req_t *vl2r = &sqp->sq_rdun.sqd_vl2r;
328
329 srp = svp->svp_remote;
330 sqp->sq_func = svp_remote_vl2_lookup_cb;
331 sqp->sq_arg = arg;
332 sqp->sq_svp = svp;
333 sqp->sq_state = SVP_QUERY_INIT;
334 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
335 sqp->sq_header.svp_op = htons(SVP_R_VL2_REQ);
336 sqp->sq_header.svp_size = htonl(sizeof (svp_vl2_req_t));
337 sqp->sq_header.svp_id = id_alloc(svp_idspace);
338 if (sqp->sq_header.svp_id == (id_t)-1)
339 libvarpd_panic("failed to allcoate from svp_idspace: %d",
340 errno);
341 sqp->sq_header.svp_crc32 = htonl(0);
342 sqp->sq_rdata = vl2r;
343 sqp->sq_rsize = sizeof (svp_vl2_req_t);
344 sqp->sq_wdata = NULL;
345 sqp->sq_wsize = 0;
346
347 bcopy(mac, vl2r->sl2r_mac, ETHERADDRL);
348 vl2r->sl2r_vnetid = ntohl(svp->svp_vid);
349
350 mutex_enter(&srp->sr_lock);
351 if (svp_remote_conn_queue(srp, sqp) == B_FALSE)
352 svp->svp_cb.scb_vl2_lookup(svp, SVP_S_FATAL, NULL, NULL, arg);
353 mutex_exit(&srp->sr_lock);
354 }
366 sra->sra_ip, sra->sra_src_pfx, sra->sra_dst_pfx, arg);
367 } else {
368 svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
369 0, 0, 0, NULL, NULL, 0, NULL, 0, 0, arg);
370 }
371 }
372
373 void
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)
377 {
378 svp_remote_t *srp;
379 svp_route_req_t *srr = &sqp->sq_rdun.sqd_rr;
380
381 srp = svp->svp_remote;
382 sqp->sq_func = svp_remote_route_lookup_cb;
383 sqp->sq_arg = arg;
384 sqp->sq_svp = svp;
385 sqp->sq_state = SVP_QUERY_INIT;
386 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
387 sqp->sq_header.svp_op = htons(SVP_R_ROUTE_REQ);
388 sqp->sq_header.svp_size = htonl(sizeof (svp_route_req_t));
389 sqp->sq_header.svp_id = id_alloc(svp_idspace);
390 if (sqp->sq_header.svp_id == (id_t)-1)
391 libvarpd_panic("failed to allcoate from svp_idspace: %d",
392 errno);
393 sqp->sq_header.svp_crc32 = htonl(0);
394 sqp->sq_rdata = srr;
395
396 bcopy(src, srr->srr_srcip, sizeof (struct in6_addr));
397 bcopy(dst, srr->srr_dstip, sizeof (struct in6_addr));
398 /* Caller should've checked both are the same type... */
399 srr->srr_vnetid = vnetid;
400 srr->srr_vlan = vlan;
401 srr->srr_pad = 0;
402
403 mutex_enter(&srp->sr_lock);
404 if (!svp_remote_conn_queue(srp, sqp)) {
405 sqp->sq_status = SVP_S_FATAL;
406 sqp->sq_func(sqp, arg);
418 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, vl3a->sl3a_mac,
419 (struct in6_addr *)vl3a->sl3a_uip, ntohs(vl3a->sl3a_uport),
420 arg);
421 else
422 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, NULL, NULL, 0,
423 arg);
424 }
425
426 static void
427 svp_remote_vl3_common(svp_remote_t *srp, svp_query_t *sqp,
428 const struct sockaddr *addr, svp_query_f func, void *arg, uint32_t vid)
429 {
430 svp_vl3_req_t *vl3r = &sqp->sq_rdun.sdq_vl3r;
431
432 if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
433 libvarpd_panic("unexpected sa_family for the vl3 lookup");
434
435 sqp->sq_func = func;
436 sqp->sq_arg = arg;
437 sqp->sq_state = SVP_QUERY_INIT;
438 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
439 sqp->sq_header.svp_op = htons(SVP_R_VL3_REQ);
440 sqp->sq_header.svp_size = htonl(sizeof (svp_vl3_req_t));
441 sqp->sq_header.svp_id = id_alloc(svp_idspace);
442 if (sqp->sq_header.svp_id == (id_t)-1)
443 libvarpd_panic("failed to allcoate from svp_idspace: %d",
444 errno);
445 sqp->sq_header.svp_crc32 = htonl(0);
446 sqp->sq_rdata = vl3r;
447 sqp->sq_rsize = sizeof (svp_vl3_req_t);
448 sqp->sq_wdata = NULL;
449 sqp->sq_wsize = 0;
450
451 if (addr->sa_family == AF_INET6) {
452 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)addr;
453 vl3r->sl3r_type = htonl(SVP_VL3_IPV6);
454 bcopy(&s6->sin6_addr, vl3r->sl3r_ip,
455 sizeof (struct in6_addr));
456 } else {
457 struct sockaddr_in *s4 = (struct sockaddr_in *)addr;
458 struct in6_addr v6;
500 svp_remote_t *srp = sqp->sq_arg;
501
502 assert(sqp->sq_wdata != NULL);
503 if (sqp->sq_status == SVP_S_OK)
504 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
505 sqp->sq_size);
506 else
507 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0);
508 }
509
510 void
511 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
512 size_t buflen)
513 {
514 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
515 boolean_t queued;
516
517 sqp->sq_func = svp_remote_log_request_cb;
518 sqp->sq_state = SVP_QUERY_INIT;
519 sqp->sq_arg = srp;
520 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
521 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
522 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
523 sqp->sq_header.svp_id = id_alloc(svp_idspace);
524 if (sqp->sq_header.svp_id == (id_t)-1)
525 libvarpd_panic("failed to allcoate from svp_idspace: %d",
526 errno);
527 sqp->sq_header.svp_crc32 = htonl(0);
528 sqp->sq_rdata = logr;
529 sqp->sq_rsize = sizeof (svp_log_req_t);
530 sqp->sq_wdata = buf;
531 sqp->sq_wsize = buflen;
532
533 logr->svlr_count = htonl(buflen);
534 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
535
536 /*
537 * If this fails, there isn't much that we can't do. Give the callback
538 * with a fatal status.
539 */
540 mutex_enter(&srp->sr_lock);
546 }
547
548 static void
549 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
550 {
551 svp_remote_t *srp = arg;
552
553 svp_shootdown_lrm_cb(srp, sqp->sq_status);
554 }
555
556 void
557 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
558 size_t buflen)
559 {
560 boolean_t queued;
561 svp_lrm_req_t *svrr = buf;
562
563 sqp->sq_func = svp_remote_lrm_request_cb;
564 sqp->sq_state = SVP_QUERY_INIT;
565 sqp->sq_arg = srp;
566 sqp->sq_header.svp_ver = htons(SVP_CURRENT_VERSION);
567 sqp->sq_header.svp_op = htons(SVP_R_LOG_RM);
568 sqp->sq_header.svp_size = htonl(buflen);
569 sqp->sq_header.svp_id = id_alloc(svp_idspace);
570 if (sqp->sq_header.svp_id == (id_t)-1)
571 libvarpd_panic("failed to allcoate from svp_idspace: %d",
572 errno);
573 sqp->sq_header.svp_crc32 = htonl(0);
574 sqp->sq_rdata = buf;
575 sqp->sq_rsize = buflen;
576 sqp->sq_wdata = NULL;
577 sqp->sq_wsize = 0;
578
579 /*
580 * We need to fix up the count to be in proper network order.
581 */
582 svrr->svrr_count = htonl(svrr->svrr_count);
583
584 /*
585 * If this fails, there isn't much that we can't do. Give the callback
586 * with a fatal status.
|
262 void
263 svp_remote_detach(svp_t *svp)
264 {
265 svp_t *lookup;
266 svp_remote_t *srp = svp->svp_remote;
267
268 if (srp == NULL)
269 libvarpd_panic("trying to detach remote when none exists");
270
271 mutex_enter(&srp->sr_lock);
272 lookup = avl_find(&srp->sr_tree, svp, NULL);
273 if (lookup == NULL || lookup != svp)
274 libvarpd_panic("inconsitent remote avl tree...");
275 avl_remove(&srp->sr_tree, svp);
276 svp->svp_remote = NULL;
277 mutex_exit(&srp->sr_lock);
278 svp_remote_release(srp);
279 }
280
281 /*
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).
287 */
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
318 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
319 {
320 svp_conn_t *scp;
321
322 assert(MUTEX_HELD(&srp->sr_lock));
323 for (scp = list_head(&srp->sr_conns); scp != NULL;
324 scp = list_next(&srp->sr_conns, scp)) {
325 mutex_enter(&scp->sc_lock);
326 if (scp->sc_cstate != SVP_CS_ACTIVE ||
327 !svp_outbound_version_check(scp->sc_version, sqp)) {
328 mutex_exit(&scp->sc_lock);
329 continue;
330 }
331 svp_conn_queue(scp, sqp);
332 mutex_exit(&scp->sc_lock);
333 list_remove(&srp->sr_conns, scp);
334 list_insert_tail(&srp->sr_conns, scp);
335 return (B_TRUE);
336 }
337
338 return (B_FALSE);
339 }
340
341 static void
342 svp_remote_vl2_lookup_cb(svp_query_t *sqp, void *arg)
343 {
344 svp_t *svp = sqp->sq_svp;
345 svp_vl2_ack_t *vl2a = (svp_vl2_ack_t *)sqp->sq_wdata;
346
347 if (sqp->sq_status == SVP_S_OK)
348 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status,
349 (struct in6_addr *)vl2a->sl2a_addr, ntohs(vl2a->sl2a_port),
350 arg);
351 else
352 svp->svp_cb.scb_vl2_lookup(svp, sqp->sq_status, NULL, 0, arg);
353 }
354
355 void
356 svp_remote_vl2_lookup(svp_t *svp, svp_query_t *sqp, const uint8_t *mac,
357 void *arg)
358 {
359 svp_remote_t *srp;
360 svp_vl2_req_t *vl2r = &sqp->sq_rdun.sqd_vl2r;
361
362 srp = svp->svp_remote;
363 sqp->sq_func = svp_remote_vl2_lookup_cb;
364 sqp->sq_arg = arg;
365 sqp->sq_svp = svp;
366 sqp->sq_state = SVP_QUERY_INIT;
367 sqp->sq_header.svp_op = htons(SVP_R_VL2_REQ);
368 sqp->sq_header.svp_size = htonl(sizeof (svp_vl2_req_t));
369 sqp->sq_header.svp_id = id_alloc(svp_idspace);
370 if (sqp->sq_header.svp_id == (id_t)-1)
371 libvarpd_panic("failed to allcoate from svp_idspace: %d",
372 errno);
373 sqp->sq_header.svp_crc32 = htonl(0);
374 sqp->sq_rdata = vl2r;
375 sqp->sq_rsize = sizeof (svp_vl2_req_t);
376 sqp->sq_wdata = NULL;
377 sqp->sq_wsize = 0;
378
379 bcopy(mac, vl2r->sl2r_mac, ETHERADDRL);
380 vl2r->sl2r_vnetid = ntohl(svp->svp_vid);
381
382 mutex_enter(&srp->sr_lock);
383 if (svp_remote_conn_queue(srp, sqp) == B_FALSE)
384 svp->svp_cb.scb_vl2_lookup(svp, SVP_S_FATAL, NULL, NULL, arg);
385 mutex_exit(&srp->sr_lock);
386 }
398 sra->sra_ip, sra->sra_src_pfx, sra->sra_dst_pfx, arg);
399 } else {
400 svp->svp_cb.scb_route_lookup(svp, sqp->sq_status,
401 0, 0, 0, NULL, NULL, 0, NULL, 0, 0, arg);
402 }
403 }
404
405 void
406 svp_remote_route_lookup(svp_t *svp, svp_query_t *sqp,
407 const struct in6_addr *src, const struct in6_addr *dst, uint32_t vnetid,
408 uint16_t vlan, void *arg)
409 {
410 svp_remote_t *srp;
411 svp_route_req_t *srr = &sqp->sq_rdun.sqd_rr;
412
413 srp = svp->svp_remote;
414 sqp->sq_func = svp_remote_route_lookup_cb;
415 sqp->sq_arg = arg;
416 sqp->sq_svp = svp;
417 sqp->sq_state = SVP_QUERY_INIT;
418 sqp->sq_header.svp_op = htons(SVP_R_ROUTE_REQ);
419 sqp->sq_header.svp_size = htonl(sizeof (svp_route_req_t));
420 sqp->sq_header.svp_id = id_alloc(svp_idspace);
421 if (sqp->sq_header.svp_id == (id_t)-1)
422 libvarpd_panic("failed to allcoate from svp_idspace: %d",
423 errno);
424 sqp->sq_header.svp_crc32 = htonl(0);
425 sqp->sq_rdata = srr;
426
427 bcopy(src, srr->srr_srcip, sizeof (struct in6_addr));
428 bcopy(dst, srr->srr_dstip, sizeof (struct in6_addr));
429 /* Caller should've checked both are the same type... */
430 srr->srr_vnetid = vnetid;
431 srr->srr_vlan = vlan;
432 srr->srr_pad = 0;
433
434 mutex_enter(&srp->sr_lock);
435 if (!svp_remote_conn_queue(srp, sqp)) {
436 sqp->sq_status = SVP_S_FATAL;
437 sqp->sq_func(sqp, arg);
449 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, vl3a->sl3a_mac,
450 (struct in6_addr *)vl3a->sl3a_uip, ntohs(vl3a->sl3a_uport),
451 arg);
452 else
453 svp->svp_cb.scb_vl3_lookup(svp, sqp->sq_status, NULL, NULL, 0,
454 arg);
455 }
456
457 static void
458 svp_remote_vl3_common(svp_remote_t *srp, svp_query_t *sqp,
459 const struct sockaddr *addr, svp_query_f func, void *arg, uint32_t vid)
460 {
461 svp_vl3_req_t *vl3r = &sqp->sq_rdun.sdq_vl3r;
462
463 if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
464 libvarpd_panic("unexpected sa_family for the vl3 lookup");
465
466 sqp->sq_func = func;
467 sqp->sq_arg = arg;
468 sqp->sq_state = SVP_QUERY_INIT;
469 sqp->sq_header.svp_op = htons(SVP_R_VL3_REQ);
470 sqp->sq_header.svp_size = htonl(sizeof (svp_vl3_req_t));
471 sqp->sq_header.svp_id = id_alloc(svp_idspace);
472 if (sqp->sq_header.svp_id == (id_t)-1)
473 libvarpd_panic("failed to allcoate from svp_idspace: %d",
474 errno);
475 sqp->sq_header.svp_crc32 = htonl(0);
476 sqp->sq_rdata = vl3r;
477 sqp->sq_rsize = sizeof (svp_vl3_req_t);
478 sqp->sq_wdata = NULL;
479 sqp->sq_wsize = 0;
480
481 if (addr->sa_family == AF_INET6) {
482 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)addr;
483 vl3r->sl3r_type = htonl(SVP_VL3_IPV6);
484 bcopy(&s6->sin6_addr, vl3r->sl3r_ip,
485 sizeof (struct in6_addr));
486 } else {
487 struct sockaddr_in *s4 = (struct sockaddr_in *)addr;
488 struct in6_addr v6;
530 svp_remote_t *srp = sqp->sq_arg;
531
532 assert(sqp->sq_wdata != NULL);
533 if (sqp->sq_status == SVP_S_OK)
534 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
535 sqp->sq_size);
536 else
537 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0);
538 }
539
540 void
541 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
542 size_t buflen)
543 {
544 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
545 boolean_t queued;
546
547 sqp->sq_func = svp_remote_log_request_cb;
548 sqp->sq_state = SVP_QUERY_INIT;
549 sqp->sq_arg = srp;
550 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
551 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
552 sqp->sq_header.svp_id = id_alloc(svp_idspace);
553 if (sqp->sq_header.svp_id == (id_t)-1)
554 libvarpd_panic("failed to allcoate from svp_idspace: %d",
555 errno);
556 sqp->sq_header.svp_crc32 = htonl(0);
557 sqp->sq_rdata = logr;
558 sqp->sq_rsize = sizeof (svp_log_req_t);
559 sqp->sq_wdata = buf;
560 sqp->sq_wsize = buflen;
561
562 logr->svlr_count = htonl(buflen);
563 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
564
565 /*
566 * If this fails, there isn't much that we can't do. Give the callback
567 * with a fatal status.
568 */
569 mutex_enter(&srp->sr_lock);
575 }
576
577 static void
578 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
579 {
580 svp_remote_t *srp = arg;
581
582 svp_shootdown_lrm_cb(srp, sqp->sq_status);
583 }
584
585 void
586 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
587 size_t buflen)
588 {
589 boolean_t queued;
590 svp_lrm_req_t *svrr = buf;
591
592 sqp->sq_func = svp_remote_lrm_request_cb;
593 sqp->sq_state = SVP_QUERY_INIT;
594 sqp->sq_arg = srp;
595 sqp->sq_header.svp_op = htons(SVP_R_LOG_RM);
596 sqp->sq_header.svp_size = htonl(buflen);
597 sqp->sq_header.svp_id = id_alloc(svp_idspace);
598 if (sqp->sq_header.svp_id == (id_t)-1)
599 libvarpd_panic("failed to allcoate from svp_idspace: %d",
600 errno);
601 sqp->sq_header.svp_crc32 = htonl(0);
602 sqp->sq_rdata = buf;
603 sqp->sq_rsize = buflen;
604 sqp->sq_wdata = NULL;
605 sqp->sq_wsize = 0;
606
607 /*
608 * We need to fix up the count to be in proper network order.
609 */
610 svrr->svrr_count = htonl(svrr->svrr_count);
611
612 /*
613 * If this fails, there isn't much that we can't do. Give the callback
614 * with a fatal status.
|