283 mutex_exit(&srp->sr_lock);
284 svp_remote_release(srp);
285 }
286
287 /*
288 * See if the request can be sent over the connection's supported version.
289 * Scribble the version in the request itself. NOTE that we do not check the
290 * version that already exists in sqp->sq_header.svp_ver, as we may be called
291 * from svp_remote_reassign() (and change versions when arriving at a new
292 * connection).
293 */
294 static boolean_t
295 svp_outbound_version_check(int version, svp_query_t *sqp)
296 {
297 uint16_t op = htons(sqp->sq_header.svp_op);
298
299 /*
300 * As of v1 -> v2, we really only need to restrict SVP_R_ROUTE_REQ
301 * as v2-only. Reflect that here.
302 *
303 * NOTE that if any message semantics change between future versions,
304 * (e.g. "in v3 SVP_R_VL2_REQ takes on additional work"), we'll
305 * need to more-deeply inspect the query. It's possible that the
306 * svp_op space is big enough to just continue op-only inspections.
307 */
308
309 assert(version > 0 && version <= SVP_CURRENT_VERSION);
310
311 if (op != SVP_R_ROUTE_REQ || version >= SVP_VERSION_TWO) {
312 sqp->sq_header.svp_ver = htons(version);
313 return (B_TRUE);
314 }
315 return (B_FALSE);
316 }
317
318 /*
319 * Walk the list of connections and find the first one that's available AND
320 * version-appropriate for the message, then move the matched connection to
321 * the back of the list so it's less likely to be used again.
322 */
323 static boolean_t
324 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
325 {
326 svp_conn_t *scp;
327
328 assert(MUTEX_HELD(&srp->sr_lock));
329 for (scp = list_head(&srp->sr_conns); scp != NULL;
330 scp = list_next(&srp->sr_conns, scp)) {
331 mutex_enter(&scp->sc_lock);
332 if (scp->sc_cstate != SVP_CS_ACTIVE ||
333 !svp_outbound_version_check(scp->sc_version, sqp)) {
334 mutex_exit(&scp->sc_lock);
524 const struct sockaddr *addr, svp_query_f func, void *arg)
525 {
526 svp_remote_vl3_common(srp, sqp, addr, func, arg, vid);
527 }
528
529 void
530 svp_remote_vl3_lookup(svp_t *svp, svp_query_t *sqp,
531 const struct sockaddr *addr, void *arg)
532 {
533 svp_remote_t *srp = svp->svp_remote;
534
535 sqp->sq_svp = svp;
536 svp_remote_vl3_common(srp, sqp, addr, svp_remote_vl3_lookup_cb,
537 arg, svp->svp_vid);
538 }
539
540 static void
541 svp_remote_log_request_cb(svp_query_t *sqp, void *arg)
542 {
543 svp_remote_t *srp = sqp->sq_arg;
544
545 assert(sqp->sq_wdata != NULL);
546 if (sqp->sq_status == SVP_S_OK)
547 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
548 sqp->sq_size);
549 else
550 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0);
551 }
552
553 void
554 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
555 size_t buflen)
556 {
557 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
558 boolean_t queued;
559
560 sqp->sq_func = svp_remote_log_request_cb;
561 sqp->sq_state = SVP_QUERY_INIT;
562 sqp->sq_arg = srp;
563 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
564 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
565 sqp->sq_header.svp_id = id_alloc(svp_idspace);
566 if (sqp->sq_header.svp_id == (id_t)-1)
567 libvarpd_panic("failed to allcoate from svp_idspace: %d",
568 errno);
569 sqp->sq_header.svp_crc32 = 0;
570 sqp->sq_rdata = logr;
571 sqp->sq_rsize = sizeof (svp_log_req_t);
572 sqp->sq_wdata = buf;
573 sqp->sq_wsize = buflen;
574
575 logr->svlr_count = htonl(buflen);
576 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
577
578 /*
579 * If this fails, there isn't much that we can't do. Give the callback
580 * with a fatal status.
581 */
582 mutex_enter(&srp->sr_lock);
583 queued = svp_remote_conn_queue(srp, sqp);
584 mutex_exit(&srp->sr_lock);
585
586 if (queued == B_FALSE)
587 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
588 }
589
590 static void
591 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
592 {
593 svp_remote_t *srp = arg;
594
595 svp_shootdown_lrm_cb(srp, sqp->sq_status);
596 }
597
598 void
599 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
600 size_t buflen)
601 {
602 boolean_t queued;
603 svp_lrm_req_t *svrr = buf;
604
605 sqp->sq_func = svp_remote_lrm_request_cb;
606 sqp->sq_state = SVP_QUERY_INIT;
607 sqp->sq_arg = srp;
614 sqp->sq_header.svp_crc32 = 0;
615 sqp->sq_rdata = buf;
616 sqp->sq_rsize = buflen;
617 sqp->sq_wdata = NULL;
618 sqp->sq_wsize = 0;
619
620 /*
621 * We need to fix up the count to be in proper network order.
622 */
623 svrr->svrr_count = htonl(svrr->svrr_count);
624
625 /*
626 * If this fails, there isn't much that we can't do. Give the callback
627 * with a fatal status.
628 */
629 mutex_enter(&srp->sr_lock);
630 queued = svp_remote_conn_queue(srp, sqp);
631 mutex_exit(&srp->sr_lock);
632
633 if (queued == B_FALSE)
634 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0);
635 }
636
637 /* ARGSUSED */
638 void
639 svp_remote_dns_timer(void *unused)
640 {
641 svp_remote_t *s;
642 mutex_enter(&svp_remote_lock);
643 for (s = avl_first(&svp_remote_tree); s != NULL;
644 s = AVL_NEXT(&svp_remote_tree, s)) {
645 svp_host_queue(s);
646 }
647 mutex_exit(&svp_remote_lock);
648 }
649
650 void
651 svp_remote_resolved(svp_remote_t *srp, struct addrinfo *newaddrs)
652 {
653 struct addrinfo *a;
654 svp_conn_t *scp;
874 squery->ssv_log = sdl;
875 squery->ssv_sock.sin6_family = AF_INET6;
876 bcopy(svl3->svl3_ip, &squery->ssv_sock.sin6_addr,
877 sizeof (svl3->svl3_ip));
878 svp_remote_vl3_logreq(srp, &squery->ssv_query, ntohl(svl3->svl3_vnetid),
879 (struct sockaddr *)&squery->ssv_sock, svp_remote_shootdown_vl3_cb,
880 squery);
881 }
882
883 void
884 svp_remote_shootdown_vl2(svp_remote_t *srp, svp_log_vl2_t *svl2)
885 {
886 svp_t *svp, lookup;
887
888 lookup.svp_vid = ntohl(svl2->svl2_vnetid);
889 mutex_enter(&srp->sr_lock);
890 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
891 svp->svp_cb.scb_vl2_invalidate(svp, svl2->svl2_mac);
892 }
893 mutex_exit(&srp->sr_lock);
894 }
895
896 int
897 svp_remote_init(void)
898 {
899 svp_idspace = id_space_create("svp_req_ids", 1, INT32_MAX);
900 if (svp_idspace == NULL)
901 return (errno);
902 avl_create(&svp_remote_tree, svp_remote_comparator,
903 sizeof (svp_remote_t), offsetof(svp_remote_t, sr_gnode));
904 svp_dns_timer.st_func = svp_remote_dns_timer;
905 svp_dns_timer.st_arg = NULL;
906 svp_dns_timer.st_oneshot = B_FALSE;
907 svp_dns_timer.st_value = svp_dns_timer_rate;
908 svp_timer_add(&svp_dns_timer);
909 return (0);
910 }
911
912 void
913 svp_remote_fini(void)
|
283 mutex_exit(&srp->sr_lock);
284 svp_remote_release(srp);
285 }
286
287 /*
288 * See if the request can be sent over the connection's supported version.
289 * Scribble the version in the request itself. NOTE that we do not check the
290 * version that already exists in sqp->sq_header.svp_ver, as we may be called
291 * from svp_remote_reassign() (and change versions when arriving at a new
292 * connection).
293 */
294 static boolean_t
295 svp_outbound_version_check(int version, svp_query_t *sqp)
296 {
297 uint16_t op = htons(sqp->sq_header.svp_op);
298
299 /*
300 * As of v1 -> v2, we really only need to restrict SVP_R_ROUTE_REQ
301 * as v2-only. Reflect that here.
302 *
303 * NOTE that if any message semantics change between versions,
304 * (e.g. "in v3 SVP_R_VL2_REQ takes on additional work"), we'll
305 * need to more-deeply inspect the query. It's possible that the
306 * svp_op space is big enough to just continue op-only inspections.
307 */
308
309 assert(version > 0 && version <= SVP_CURRENT_VERSION);
310
311 if (op != SVP_R_ROUTE_REQ || version >= SVP_VERSION_TWO) {
312 sqp->sq_header.svp_ver = htons(version);
313 return (B_TRUE);
314 }
315
316 return (B_FALSE);
317 }
318
319 /*
320 * Walk the list of connections and find the first one that's available AND
321 * version-appropriate for the message, then move the matched connection to
322 * the back of the list so it's less likely to be used again.
323 */
324 static boolean_t
325 svp_remote_conn_queue(svp_remote_t *srp, svp_query_t *sqp)
326 {
327 svp_conn_t *scp;
328
329 assert(MUTEX_HELD(&srp->sr_lock));
330 for (scp = list_head(&srp->sr_conns); scp != NULL;
331 scp = list_next(&srp->sr_conns, scp)) {
332 mutex_enter(&scp->sc_lock);
333 if (scp->sc_cstate != SVP_CS_ACTIVE ||
334 !svp_outbound_version_check(scp->sc_version, sqp)) {
335 mutex_exit(&scp->sc_lock);
525 const struct sockaddr *addr, svp_query_f func, void *arg)
526 {
527 svp_remote_vl3_common(srp, sqp, addr, func, arg, vid);
528 }
529
530 void
531 svp_remote_vl3_lookup(svp_t *svp, svp_query_t *sqp,
532 const struct sockaddr *addr, void *arg)
533 {
534 svp_remote_t *srp = svp->svp_remote;
535
536 sqp->sq_svp = svp;
537 svp_remote_vl3_common(srp, sqp, addr, svp_remote_vl3_lookup_cb,
538 arg, svp->svp_vid);
539 }
540
541 static void
542 svp_remote_log_request_cb(svp_query_t *sqp, void *arg)
543 {
544 svp_remote_t *srp = sqp->sq_arg;
545 uint16_t version;
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
555 assert(sqp->sq_wdata != NULL);
556 if (sqp->sq_status == SVP_S_OK)
557 svp_shootdown_logr_cb(srp, sqp->sq_status, sqp->sq_wdata,
558 sqp->sq_size, version);
559 else
560 svp_shootdown_logr_cb(srp, sqp->sq_status, NULL, 0, 0);
561 }
562
563 void
564 svp_remote_log_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
565 size_t buflen)
566 {
567 svp_log_req_t *logr = &sqp->sq_rdun.sdq_logr;
568 boolean_t queued;
569
570 sqp->sq_func = svp_remote_log_request_cb;
571 sqp->sq_state = SVP_QUERY_INIT;
572 sqp->sq_arg = srp;
573 sqp->sq_header.svp_op = htons(SVP_R_LOG_REQ);
574 sqp->sq_header.svp_size = htonl(sizeof (svp_log_req_t));
575 sqp->sq_header.svp_id = id_alloc(svp_idspace);
576 if (sqp->sq_header.svp_id == (id_t)-1)
577 libvarpd_panic("failed to allcoate from svp_idspace: %d",
578 errno);
579 sqp->sq_header.svp_crc32 = 0;
580 sqp->sq_rdata = logr;
581 sqp->sq_rsize = sizeof (svp_log_req_t);
582 sqp->sq_wdata = buf;
583 sqp->sq_wsize = buflen;
584
585 logr->svlr_count = htonl(buflen);
586 bcopy(&srp->sr_uip, logr->svlr_ip, sizeof (struct in6_addr));
587
588 /*
589 * If this fails, there isn't much that we can't do. Give the callback
590 * with a fatal status.
591 */
592 mutex_enter(&srp->sr_lock);
593 queued = svp_remote_conn_queue(srp, sqp);
594 mutex_exit(&srp->sr_lock);
595
596 if (queued == B_FALSE)
597 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0, 0);
598 }
599
600 static void
601 svp_remote_lrm_request_cb(svp_query_t *sqp, void *arg)
602 {
603 svp_remote_t *srp = arg;
604
605 svp_shootdown_lrm_cb(srp, sqp->sq_status);
606 }
607
608 void
609 svp_remote_lrm_request(svp_remote_t *srp, svp_query_t *sqp, void *buf,
610 size_t buflen)
611 {
612 boolean_t queued;
613 svp_lrm_req_t *svrr = buf;
614
615 sqp->sq_func = svp_remote_lrm_request_cb;
616 sqp->sq_state = SVP_QUERY_INIT;
617 sqp->sq_arg = srp;
624 sqp->sq_header.svp_crc32 = 0;
625 sqp->sq_rdata = buf;
626 sqp->sq_rsize = buflen;
627 sqp->sq_wdata = NULL;
628 sqp->sq_wsize = 0;
629
630 /*
631 * We need to fix up the count to be in proper network order.
632 */
633 svrr->svrr_count = htonl(svrr->svrr_count);
634
635 /*
636 * If this fails, there isn't much that we can't do. Give the callback
637 * with a fatal status.
638 */
639 mutex_enter(&srp->sr_lock);
640 queued = svp_remote_conn_queue(srp, sqp);
641 mutex_exit(&srp->sr_lock);
642
643 if (queued == B_FALSE)
644 svp_shootdown_logr_cb(srp, SVP_S_FATAL, NULL, 0, 0);
645 }
646
647 /* ARGSUSED */
648 void
649 svp_remote_dns_timer(void *unused)
650 {
651 svp_remote_t *s;
652 mutex_enter(&svp_remote_lock);
653 for (s = avl_first(&svp_remote_tree); s != NULL;
654 s = AVL_NEXT(&svp_remote_tree, s)) {
655 svp_host_queue(s);
656 }
657 mutex_exit(&svp_remote_lock);
658 }
659
660 void
661 svp_remote_resolved(svp_remote_t *srp, struct addrinfo *newaddrs)
662 {
663 struct addrinfo *a;
664 svp_conn_t *scp;
884 squery->ssv_log = sdl;
885 squery->ssv_sock.sin6_family = AF_INET6;
886 bcopy(svl3->svl3_ip, &squery->ssv_sock.sin6_addr,
887 sizeof (svl3->svl3_ip));
888 svp_remote_vl3_logreq(srp, &squery->ssv_query, ntohl(svl3->svl3_vnetid),
889 (struct sockaddr *)&squery->ssv_sock, svp_remote_shootdown_vl3_cb,
890 squery);
891 }
892
893 void
894 svp_remote_shootdown_vl2(svp_remote_t *srp, svp_log_vl2_t *svl2)
895 {
896 svp_t *svp, lookup;
897
898 lookup.svp_vid = ntohl(svl2->svl2_vnetid);
899 mutex_enter(&srp->sr_lock);
900 if ((svp = avl_find(&srp->sr_tree, &lookup, NULL)) != NULL) {
901 svp->svp_cb.scb_vl2_invalidate(svp, svl2->svl2_mac);
902 }
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);
919 }
920
921 int
922 svp_remote_init(void)
923 {
924 svp_idspace = id_space_create("svp_req_ids", 1, INT32_MAX);
925 if (svp_idspace == NULL)
926 return (errno);
927 avl_create(&svp_remote_tree, svp_remote_comparator,
928 sizeof (svp_remote_t), offsetof(svp_remote_t, sr_gnode));
929 svp_dns_timer.st_func = svp_remote_dns_timer;
930 svp_dns_timer.st_arg = NULL;
931 svp_dns_timer.st_oneshot = B_FALSE;
932 svp_dns_timer.st_value = svp_dns_timer_rate;
933 svp_timer_add(&svp_dns_timer);
934 return (0);
935 }
936
937 void
938 svp_remote_fini(void)
|