Print this page
OS-7088 cyclics corked on overlay socket with full queue


 190                         mutex_exit(&mux->omux_lock);
 191                         OVERLAY_FREEMSG(mp, "dev dropped");
 192                         freemsg(mp);
 193                         continue;
 194                 }
 195                 overlay_io_start(odd, OVERLAY_F_IN_RX);
 196                 mutex_exit(&odd->odd_lock);
 197                 mutex_exit(&mux->omux_lock);
 198 
 199                 mac_rx(odd->odd_mh, NULL, mp);
 200 
 201                 mutex_enter(&odd->odd_lock);
 202                 overlay_io_done(odd, OVERLAY_F_IN_RX);
 203                 mutex_exit(&odd->odd_lock);
 204         }
 205 
 206         return (B_TRUE);
 207 }
 208 
 209 /*





























































 210  * Register a given device with a socket backend. If no such device socket
 211  * exists, create a new one.
 212  */
 213 overlay_mux_t *
 214 overlay_mux_open(overlay_plugin_t *opp, int domain, int family, int protocol,
 215     struct sockaddr *addr, socklen_t len, int *errp)
 216 {
 217         int err;
 218         overlay_mux_t *mux;
 219         ksocket_t ksock;

 220 
 221         if (errp == NULL)
 222                 errp = &err;
 223 
 224         mutex_enter(&overlay_mux_lock);
 225         for (mux = list_head(&overlay_mux_list); mux != NULL;
 226             mux = list_next(&overlay_mux_list, mux)) {
 227                 if (domain == mux->omux_domain &&
 228                     family == mux->omux_family &&
 229                     protocol == mux->omux_protocol &&
 230                     len == mux->omux_alen &&
 231                     bcmp(addr, mux->omux_addr, len) == 0) {
 232 
 233                         if (opp != mux->omux_plugin) {
 234                                 *errp = EEXIST;
 235                                 return (NULL);
 236                         }
 237 
 238                         mutex_enter(&mux->omux_lock);
 239                         mux->omux_count++;


 273                 mutex_exit(&overlay_mux_lock);
 274                 ksocket_close(ksock, kcred);
 275                 return (NULL);
 276         }
 277 
 278         mux = kmem_alloc(sizeof (overlay_mux_t), KM_SLEEP);
 279         list_link_init(&mux->omux_lnode);
 280         mux->omux_ksock = ksock;
 281         mux->omux_plugin = opp;
 282         mux->omux_domain = domain;
 283         mux->omux_family = family;
 284         mux->omux_protocol = protocol;
 285         mux->omux_addr = kmem_alloc(len, KM_SLEEP);
 286         bcopy(addr, mux->omux_addr, len);
 287         mux->omux_alen = len;
 288         mux->omux_count = 1;
 289         avl_create(&mux->omux_devices, overlay_mux_comparator,
 290             sizeof (overlay_dev_t), offsetof(overlay_dev_t, odd_muxnode));
 291         mutex_init(&mux->omux_lock, NULL, MUTEX_DRIVER, NULL);
 292 



 293 


























 294         /* Once this is called, we need to expect to rx data */
 295         *errp = ksocket_krecv_set(ksock, overlay_mux_recv, mux);
 296         if (*errp != 0) {
 297                 ksocket_close(ksock, kcred);
 298                 mutex_destroy(&mux->omux_lock);
 299                 avl_destroy(&mux->omux_devices);
 300                 kmem_free(mux->omux_addr, len);
 301                 kmem_free(mux, sizeof (overlay_mux_t));
 302                 return (NULL);
 303         }
 304 
 305         list_insert_tail(&overlay_mux_list, mux);
 306         mutex_exit(&overlay_mux_lock);
 307 
 308         *errp = 0;
 309         return (mux);
 310 }
 311 
 312 void
 313 overlay_mux_close(overlay_mux_t *mux)


 337         avl_add(&mux->omux_devices, odd);
 338         mutex_exit(&mux->omux_lock);
 339 }
 340 
 341 void
 342 overlay_mux_remove_dev(overlay_mux_t *mux, overlay_dev_t *odd)
 343 {
 344         mutex_enter(&mux->omux_lock);
 345         avl_remove(&mux->omux_devices, odd);
 346         mutex_exit(&mux->omux_lock);
 347 }
 348 
 349 int
 350 overlay_mux_tx(overlay_mux_t *mux, struct msghdr *hdr, mblk_t *mp)
 351 {
 352         int ret;
 353 
 354         /*
 355          * It'd be nice to be able to use MSG_MBLK_QUICKRELE, unfortunately,
 356          * that isn't actually supported by UDP at this time.


 357          */
 358         ret = ksocket_sendmblk(mux->omux_ksock, hdr, 0, &mp, kcred);






 359         if (ret != 0)
 360                 freemsg(mp);
 361 
 362         return (ret);
 363 }


 190                         mutex_exit(&mux->omux_lock);
 191                         OVERLAY_FREEMSG(mp, "dev dropped");
 192                         freemsg(mp);
 193                         continue;
 194                 }
 195                 overlay_io_start(odd, OVERLAY_F_IN_RX);
 196                 mutex_exit(&odd->odd_lock);
 197                 mutex_exit(&mux->omux_lock);
 198 
 199                 mac_rx(odd->odd_mh, NULL, mp);
 200 
 201                 mutex_enter(&odd->odd_lock);
 202                 overlay_io_done(odd, OVERLAY_F_IN_RX);
 203                 mutex_exit(&odd->odd_lock);
 204         }
 205 
 206         return (B_TRUE);
 207 }
 208 
 209 /*
 210  * Kernel socket callback to indicate the socket itself is able to send
 211  * data again.  Check for devices on this mux that were send-blocked,
 212  * and clear them.
 213  */
 214 /* ARGSUSED */
 215 static void
 216 overlay_mux_cansend_now(ksocket_t ksock, ksocket_callback_event_t event,
 217     void *arg, uintptr_t ignore_me)
 218 {
 219         overlay_mux_t *mux = (overlay_mux_t *)arg;
 220         overlay_dev_t *odd;
 221         mac_handle_t *mhs_to_update, *current_mh;
 222         size_t allocsize;
 223 
 224         ASSERT3P(ksock, ==, mux->omux_ksock);
 225         ASSERT3U(event, ==, KSOCKET_EV_CANSEND);
 226 
 227         /* Traverse omux_devices and check for ones marked as send-blocked. */
 228         mutex_enter(&mux->omux_lock);
 229         if (mux->omux_count == 0) {
 230                 /* Nothing to wake up. */
 231                 mutex_exit(&mux->omux_lock);
 232                 return;
 233         }
 234         allocsize = sizeof (mac_handle_t) * mux->omux_count;
 235         mhs_to_update = kmem_zalloc(allocsize, KM_NOSLEEP);
 236         VERIFY(mhs_to_update != NULL);  /* Failure should be rare. */
 237         current_mh = mhs_to_update;
 238 
 239         for (odd = avl_first(&mux->omux_devices); odd != NULL;
 240             odd = AVL_NEXT(&mux->omux_devices, odd)) {
 241                 mac_handle_t odd_mh = NULL;
 242 
 243                 mutex_enter(&odd->odd_lock);
 244                 if ((odd->odd_flags & OVERLAY_F_TXSTOPPED) != 0) {
 245                         /* Get ready to tell MAC it can transmit again. */
 246                         odd->odd_flags &= ~OVERLAY_F_TXSTOPPED;
 247                         odd_mh = odd->odd_mh;
 248                 }
 249                 mutex_exit(&odd->odd_lock);
 250                 if (odd_mh != NULL) {
 251                         *current_mh = odd_mh;
 252                         current_mh++;
 253                 }
 254         }
 255         mutex_exit(&mux->omux_lock);
 256 
 257         /*
 258          * Yes, I'm using the value-then-decrement.  "current_mh" is
 259          * guaranteed to be at least one ahead of mhs_to_update if there are
 260          * any mac handles that need updating.  I also have to do this outside
 261          * the omux lock because the tx_update may trigger immediate or
 262          * concurrent packet transmission.
 263          */
 264         while (current_mh-- != mhs_to_update)
 265                 mac_tx_update(*current_mh);
 266 
 267         kmem_free(mhs_to_update, allocsize);
 268 }
 269 
 270 /*
 271  * Register a given device with a socket backend. If no such device socket
 272  * exists, create a new one.
 273  */
 274 overlay_mux_t *
 275 overlay_mux_open(overlay_plugin_t *opp, int domain, int family, int protocol,
 276     struct sockaddr *addr, socklen_t len, int *errp)
 277 {
 278         int err;
 279         overlay_mux_t *mux;
 280         ksocket_t ksock;
 281         ksocket_callbacks_t ks_cb = { 0 };
 282 
 283         if (errp == NULL)
 284                 errp = &err;
 285 
 286         mutex_enter(&overlay_mux_lock);
 287         for (mux = list_head(&overlay_mux_list); mux != NULL;
 288             mux = list_next(&overlay_mux_list, mux)) {
 289                 if (domain == mux->omux_domain &&
 290                     family == mux->omux_family &&
 291                     protocol == mux->omux_protocol &&
 292                     len == mux->omux_alen &&
 293                     bcmp(addr, mux->omux_addr, len) == 0) {
 294 
 295                         if (opp != mux->omux_plugin) {
 296                                 *errp = EEXIST;
 297                                 return (NULL);
 298                         }
 299 
 300                         mutex_enter(&mux->omux_lock);
 301                         mux->omux_count++;


 335                 mutex_exit(&overlay_mux_lock);
 336                 ksocket_close(ksock, kcred);
 337                 return (NULL);
 338         }
 339 
 340         mux = kmem_alloc(sizeof (overlay_mux_t), KM_SLEEP);
 341         list_link_init(&mux->omux_lnode);
 342         mux->omux_ksock = ksock;
 343         mux->omux_plugin = opp;
 344         mux->omux_domain = domain;
 345         mux->omux_family = family;
 346         mux->omux_protocol = protocol;
 347         mux->omux_addr = kmem_alloc(len, KM_SLEEP);
 348         bcopy(addr, mux->omux_addr, len);
 349         mux->omux_alen = len;
 350         mux->omux_count = 1;
 351         avl_create(&mux->omux_devices, overlay_mux_comparator,
 352             sizeof (overlay_dev_t), offsetof(overlay_dev_t, odd_muxnode));
 353         mutex_init(&mux->omux_lock, NULL, MUTEX_DRIVER, NULL);
 354 
 355 #if defined(OVERLAY_PINCH) || defined(OVERLAY_FC_TEST)
 356         /* Set the xmit buf to a REALLY SMALL value, say 12k (1-3 packets) */
 357         int bufsize = 12 * 1024;
 358 
 359         if (ksocket_setsockopt(ksock, SOL_SOCKET, SO_SNDBUF,
 360                 (const void *)&bufsize, sizeof (bufsize), CRED()) != 0) {
 361                 ksocket_close(ksock, kcred);
 362                 mutex_destroy(&mux->omux_lock);
 363                 avl_destroy(&mux->omux_devices);
 364                 kmem_free(mux->omux_addr, len);
 365                 kmem_free(mux, sizeof (overlay_mux_t));
 366                 return (NULL);
 367         }
 368 #endif
 369         /*
 370          * Set a callback in case we hit socket flow control and need to know
 371          * when it's ready to send again.  See the aforementioned
 372          * ksocket_socket() comments about the use of kcred vs. being
 373          * zone-aware.
 374          */
 375         ks_cb.ksock_cb_cansend = overlay_mux_cansend_now;
 376         if (ksocket_setcallbacks(ksock, &ks_cb, mux, kcred) != 0) {
 377                 ksocket_close(ksock, kcred);
 378                 mutex_destroy(&mux->omux_lock);
 379                 avl_destroy(&mux->omux_devices);
 380                 kmem_free(mux->omux_addr, len);
 381                 kmem_free(mux, sizeof (overlay_mux_t));
 382                 return (NULL);
 383         }
 384 
 385         /* Once this is called, we need to expect to rx data */
 386         *errp = ksocket_krecv_set(ksock, overlay_mux_recv, mux);
 387         if (*errp != 0) {
 388                 ksocket_close(ksock, kcred);
 389                 mutex_destroy(&mux->omux_lock);
 390                 avl_destroy(&mux->omux_devices);
 391                 kmem_free(mux->omux_addr, len);
 392                 kmem_free(mux, sizeof (overlay_mux_t));
 393                 return (NULL);
 394         }
 395 
 396         list_insert_tail(&overlay_mux_list, mux);
 397         mutex_exit(&overlay_mux_lock);
 398 
 399         *errp = 0;
 400         return (mux);
 401 }
 402 
 403 void
 404 overlay_mux_close(overlay_mux_t *mux)


 428         avl_add(&mux->omux_devices, odd);
 429         mutex_exit(&mux->omux_lock);
 430 }
 431 
 432 void
 433 overlay_mux_remove_dev(overlay_mux_t *mux, overlay_dev_t *odd)
 434 {
 435         mutex_enter(&mux->omux_lock);
 436         avl_remove(&mux->omux_devices, odd);
 437         mutex_exit(&mux->omux_lock);
 438 }
 439 
 440 int
 441 overlay_mux_tx(overlay_mux_t *mux, struct msghdr *hdr, mblk_t *mp)
 442 {
 443         int ret;
 444 
 445         /*
 446          * It'd be nice to be able to use MSG_MBLK_QUICKRELE, unfortunately,
 447          * that isn't actually supported by UDP at this time.
 448          *
 449          * Send with MSG_DONTWAIT to indicate clogged UDP sockets upstack.
 450          */
 451         ret = ksocket_sendmblk(mux->omux_ksock, hdr, MSG_DONTWAIT, &mp, kcred);
 452         /*
 453          * NOTE: ksocket_sendmblk() may send partial packets downstack,
 454          * returning what's not sent in &mp (i.e. mp pre-call might be a
 455          * b_cont of mp post-call).  We can't hold up this message (it's a
 456          * datagram), so we drop, and let the caller cope.
 457          */
 458         if (ret != 0)
 459                 freemsg(mp);
 460 
 461         return (ret);
 462 }