298 * ------
299 *
300 * We maintain a single timer based on CLOCK_REALTIME. It's designed to fire
301 * every second. While we'd rather use CLOCK_HIGHRES just to alleviate ourselves
302 * from timer drift; however, as zones may not actually have CLOCK_HIGHRES
303 * access, we don't want them to end up in there. The timer itself is just a
304 * simple avl tree sorted by expiration time, which is stored as a tick in the
305 * future, a tick is just one second.
306 *
307 * ----------
308 * Shootdowns
309 * ----------
310 *
311 * As part of the protocol, we need to be able to handle shootdowns that inform
312 * us some of the information in the system is out of date. This information
313 * needs to be processed promptly; however, the information is hopefully going
314 * to be relatively infrequent relative to the normal flow of information.
315 *
316 * The shoot down information needs to be done on a per-backend basis. The
317 * general design is that we'll have a single query for this which can fire on a
318 * 5-10s period, we randmoize the latter part to give us a bit more load
319 * spreading. If we complete because there's no work to do, then we wait the
320 * normal period. If we complete, but there's still work to do, we'll go again
321 * after a second.
322 *
323 * A shootdown has a few different parts. We first receive a list of items to
324 * shootdown. After performing all of those, we need to acknowledge them. When
325 * that's been done successfully, we can move onto the next part. From a
326 * protocol perspective, we make a SVP_R_LOG_REQ, we get a reply, and then after
327 * processing them, send an SVP_R_LOG_RM. Only once that's been acked do we
328 * continue.
329 *
330 * However, one of the challenges that we have is that these invalidations are
331 * just that, an invalidation. For a virtual layer two request, that's fine,
332 * because the kernel supports that. However, for virtual layer three
333 * invalidations, we have a bit more work to do. These protocols, ARP and NDP,
334 * don't really support a notion of just an invalidation, instead you have to
335 * inject the new data in a gratuitous fashion.
336 *
337 * To that end, what we instead do is when we receive a VL3 invalidation, we
338 * turn that info a VL3 request. We hold the general request as outstanding
525 }
526
527 otp = svl->svl_u.svl_route.svl_point;
528 bcopy(ul3_addr, &otp->otp_ip, sizeof (struct in6_addr));
529 otp->otp_port = ul3_port;
530
531 otr = svl->svl_u.svl_route.svl_route;
532 otr->otr_vnet = vnetid;
533 otr->otr_vlan = vlan;
534 bcopy(srcmac, otr->otr_srcmac, ETHERADDRL);
535
536 otm = svl->svl_u.svl_route.svl_mac;
537 otm->otm_dcid = dcid;
538 bcopy(dstmac, otm->otm_mac, ETHERADDRL);
539
540 libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
541 VARPD_LOOKUP_OK);
542 umem_cache_free(svp_lookup_cache, svl);
543 }
544
545 static svp_cb_t svp_defops = {
546 svp_vl2_lookup_cb,
547 svp_vl3_lookup_cb,
548 svp_vl2_invalidate_cb,
549 svp_vl3_inject_cb,
550 svp_shootdown_cb,
551 svp_route_lookup_cb,
552 };
553
554 static boolean_t
555 varpd_svp_valid_dest(overlay_plugin_dest_t dest)
556 {
557 if (dest != (OVERLAY_PLUGIN_D_IP | OVERLAY_PLUGIN_D_PORT))
558 return (B_FALSE);
559
560 return (B_TRUE);
561 }
562
563 static int
564 varpd_svp_create(varpd_provider_handle_t *hdl, void **outp,
565 overlay_plugin_dest_t dest)
566 {
567 int ret;
568 svp_t *svp;
569
570 if (varpd_svp_valid_dest(dest) == B_FALSE)
571 return (ENOTSUP);
|
298 * ------
299 *
300 * We maintain a single timer based on CLOCK_REALTIME. It's designed to fire
301 * every second. While we'd rather use CLOCK_HIGHRES just to alleviate ourselves
302 * from timer drift; however, as zones may not actually have CLOCK_HIGHRES
303 * access, we don't want them to end up in there. The timer itself is just a
304 * simple avl tree sorted by expiration time, which is stored as a tick in the
305 * future, a tick is just one second.
306 *
307 * ----------
308 * Shootdowns
309 * ----------
310 *
311 * As part of the protocol, we need to be able to handle shootdowns that inform
312 * us some of the information in the system is out of date. This information
313 * needs to be processed promptly; however, the information is hopefully going
314 * to be relatively infrequent relative to the normal flow of information.
315 *
316 * The shoot down information needs to be done on a per-backend basis. The
317 * general design is that we'll have a single query for this which can fire on a
318 * 5-10s period, we randomize the latter part to give us a bit more load
319 * spreading. If we complete because there's no work to do, then we wait the
320 * normal period. If we complete, but there's still work to do, we'll go again
321 * after a second.
322 *
323 * A shootdown has a few different parts. We first receive a list of items to
324 * shootdown. After performing all of those, we need to acknowledge them. When
325 * that's been done successfully, we can move onto the next part. From a
326 * protocol perspective, we make a SVP_R_LOG_REQ, we get a reply, and then after
327 * processing them, send an SVP_R_LOG_RM. Only once that's been acked do we
328 * continue.
329 *
330 * However, one of the challenges that we have is that these invalidations are
331 * just that, an invalidation. For a virtual layer two request, that's fine,
332 * because the kernel supports that. However, for virtual layer three
333 * invalidations, we have a bit more work to do. These protocols, ARP and NDP,
334 * don't really support a notion of just an invalidation, instead you have to
335 * inject the new data in a gratuitous fashion.
336 *
337 * To that end, what we instead do is when we receive a VL3 invalidation, we
338 * turn that info a VL3 request. We hold the general request as outstanding
525 }
526
527 otp = svl->svl_u.svl_route.svl_point;
528 bcopy(ul3_addr, &otp->otp_ip, sizeof (struct in6_addr));
529 otp->otp_port = ul3_port;
530
531 otr = svl->svl_u.svl_route.svl_route;
532 otr->otr_vnet = vnetid;
533 otr->otr_vlan = vlan;
534 bcopy(srcmac, otr->otr_srcmac, ETHERADDRL);
535
536 otm = svl->svl_u.svl_route.svl_mac;
537 otm->otm_dcid = dcid;
538 bcopy(dstmac, otm->otm_mac, ETHERADDRL);
539
540 libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
541 VARPD_LOOKUP_OK);
542 umem_cache_free(svp_lookup_cache, svl);
543 }
544
545 /*
546 * Tell the overlay instance to flush out entries matcthing this route.
547 * See libvarpd_route_flush() for more.
548 */
549 static void
550 svp_route_shootdown_cb(svp_t *svp, uint8_t *srcip, uint8_t *dstip,
551 uint8_t src_prefixlen, uint8_t dst_prefixlen, uint16_t vlan_id)
552 {
553 libvarpd_route_flush(svp->svp_hdl, srcip, dstip, src_prefixlen,
554 dst_prefixlen, vlan_id);
555 }
556
557 static svp_cb_t svp_defops = {
558 svp_vl2_lookup_cb,
559 svp_vl3_lookup_cb,
560 svp_vl2_invalidate_cb,
561 svp_vl3_inject_cb,
562 svp_shootdown_cb,
563 svp_route_lookup_cb,
564 svp_route_shootdown_cb
565 };
566
567 static boolean_t
568 varpd_svp_valid_dest(overlay_plugin_dest_t dest)
569 {
570 if (dest != (OVERLAY_PLUGIN_D_IP | OVERLAY_PLUGIN_D_PORT))
571 return (B_FALSE);
572
573 return (B_TRUE);
574 }
575
576 static int
577 varpd_svp_create(varpd_provider_handle_t *hdl, void **outp,
578 overlay_plugin_dest_t dest)
579 {
580 int ret;
581 svp_t *svp;
582
583 if (varpd_svp_valid_dest(dest) == B_FALSE)
584 return (ENOTSUP);
|