Print this page
OS-7088 cyclics corked on overlay socket with full queue
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Overlay Devices
  18  *
  19  * Overlay devices provide a means for creating overlay networks, a means of
  20  * multiplexing multiple logical, isolated, and discrete layer two and layer
  21  * three networks on top of one physical network.
  22  *
  23  * In general, these overlay devices encapsulate the logic to answer two
  24  * different questions:
  25  *
  26  *   1) How should I transform a packet to put it on the wire?
  27  *   2) Where should I send a transformed packet?
  28  *
  29  * Each overlay device is presented to the user as a GLDv3 device. While the
  30  * link itself cannot have an IP interface created on top of it, it allows for
  31  * additional GLDv3 devices, such as a VNIC, to be created on top of it which
  32  * can be plumbed up with IP interfaces.
  33  *


1037 /*
1038  * For more info on this, see the big theory statement.
1039  */
1040 /* ARGSUSED */
1041 static int
1042 overlay_m_unicast(void *arg, const uint8_t *macaddr)
1043 {
1044         return (0);
1045 }
1046 
1047 mblk_t *
1048 overlay_m_tx(void *arg, mblk_t *mp_chain)
1049 {
1050         overlay_dev_t *odd = arg;
1051         mblk_t *mp, *ep;
1052         int ret;
1053         ovep_encap_info_t einfo;
1054         struct msghdr hdr;
1055 
1056         mutex_enter(&odd->odd_lock);

1057         if ((odd->odd_flags & OVERLAY_F_MDDROP) ||
1058             !(odd->odd_flags & OVERLAY_F_IN_MUX)) {
1059                 mutex_exit(&odd->odd_lock);
1060                 freemsgchain(mp_chain);
1061                 return (NULL);
1062         }
1063         overlay_io_start(odd, OVERLAY_F_IN_TX);
1064         mutex_exit(&odd->odd_lock);
1065 
1066         bzero(&hdr, sizeof (struct msghdr));
1067 
1068         bzero(&einfo, sizeof (ovep_encap_info_t));
1069         einfo.ovdi_id = odd->odd_vid;
1070         mp = mp_chain;
1071         while (mp != NULL) {
1072                 socklen_t slen;
1073                 struct sockaddr_storage storage;




1074 
1075                 mp_chain = mp->b_next;
1076                 mp->b_next = NULL;
1077                 ep = NULL;
1078 
1079                 ret = overlay_target_lookup(odd, mp,
1080                     (struct sockaddr *)&storage, &slen);
1081                 if (ret != OVERLAY_TARGET_OK) {
1082                         if (ret == OVERLAY_TARGET_DROP)
1083                                 freemsg(mp);
1084                         mp = mp_chain;



1085                         continue;
1086                 }
1087 
1088                 hdr.msg_name = &storage;
1089                 hdr.msg_namelen = slen;
1090 
1091                 ret = odd->odd_plugin->ovp_ops->ovpo_encap(odd->odd_mh, mp,
1092                     &einfo, &ep);
1093                 if (ret != 0 || ep == NULL) {



1094                         freemsg(mp);
1095                         goto out;
1096                 }
1097 
1098                 ASSERT(ep->b_cont == mp || ep == mp);
1099                 ret = overlay_mux_tx(odd->odd_mux, &hdr, ep);
1100                 if (ret != 0)






























1101                         goto out;

1102 
1103                 mp = mp_chain;
1104         }
1105 
1106 out:
1107         mutex_enter(&odd->odd_lock);
1108         overlay_io_done(odd, OVERLAY_F_IN_TX);




1109         mutex_exit(&odd->odd_lock);
1110         return (mp_chain);
1111 }
1112 
1113 /* ARGSUSED */
1114 static void
1115 overlay_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
1116 {
1117         miocnak(q, mp, 0, ENOTSUP);
1118 }
1119 
1120 /* ARGSUSED */
1121 static boolean_t
1122 overlay_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1123 {
1124         /*
1125          * Tell MAC we're an overlay.
1126          */
1127         if (cap == MAC_CAPAB_OVERLAY)
1128                 return (B_TRUE);


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2018 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Overlay Devices
  18  *
  19  * Overlay devices provide a means for creating overlay networks, a means of
  20  * multiplexing multiple logical, isolated, and discrete layer two and layer
  21  * three networks on top of one physical network.
  22  *
  23  * In general, these overlay devices encapsulate the logic to answer two
  24  * different questions:
  25  *
  26  *   1) How should I transform a packet to put it on the wire?
  27  *   2) Where should I send a transformed packet?
  28  *
  29  * Each overlay device is presented to the user as a GLDv3 device. While the
  30  * link itself cannot have an IP interface created on top of it, it allows for
  31  * additional GLDv3 devices, such as a VNIC, to be created on top of it which
  32  * can be plumbed up with IP interfaces.
  33  *


1037 /*
1038  * For more info on this, see the big theory statement.
1039  */
1040 /* ARGSUSED */
1041 static int
1042 overlay_m_unicast(void *arg, const uint8_t *macaddr)
1043 {
1044         return (0);
1045 }
1046 
1047 mblk_t *
1048 overlay_m_tx(void *arg, mblk_t *mp_chain)
1049 {
1050         overlay_dev_t *odd = arg;
1051         mblk_t *mp, *ep;
1052         int ret;
1053         ovep_encap_info_t einfo;
1054         struct msghdr hdr;
1055 
1056         mutex_enter(&odd->odd_lock);
1057         ASSERT0(odd->odd_flags & OVERLAY_F_TXSTOPPED);
1058         if ((odd->odd_flags & OVERLAY_F_MDDROP) ||
1059             !(odd->odd_flags & OVERLAY_F_IN_MUX)) {
1060                 mutex_exit(&odd->odd_lock);
1061                 freemsgchain(mp_chain);
1062                 return (NULL);
1063         }
1064         overlay_io_start(odd, OVERLAY_F_IN_TX);
1065         mutex_exit(&odd->odd_lock);
1066 
1067         bzero(&hdr, sizeof (struct msghdr));
1068 
1069         bzero(&einfo, sizeof (ovep_encap_info_t));
1070         einfo.ovdi_id = odd->odd_vid;
1071         mp = mp_chain;
1072         while (mp != NULL) {
1073                 socklen_t slen;
1074                 struct sockaddr_storage storage;
1075 #ifdef OVERLAY_FC_TEST
1076                 /* Can deal with it being NULL later... */
1077                 mblk_t *save_mp = msgpullup(mp, -1);
1078 #endif
1079 
1080                 mp_chain = mp->b_next;
1081                 mp->b_next = NULL;
1082                 ep = NULL;
1083 
1084                 ret = overlay_target_lookup(odd, mp,
1085                     (struct sockaddr *)&storage, &slen);
1086                 if (ret != OVERLAY_TARGET_OK) {
1087                         if (ret == OVERLAY_TARGET_DROP)
1088                                 freemsg(mp);
1089                         mp = mp_chain;
1090 #ifdef OVERLAY_FC_TEST
1091                         freemsg(save_mp);       /* Handles NULL and non-NULL */
1092 #endif
1093                         continue;
1094                 }
1095 
1096                 hdr.msg_name = &storage;
1097                 hdr.msg_namelen = slen;
1098 
1099                 ret = odd->odd_plugin->ovp_ops->ovpo_encap(odd->odd_mh, mp,
1100                     &einfo, &ep);
1101                 if (ret != 0 || ep == NULL) {
1102 #ifdef OVERLAY_FC_TEST
1103                         freemsg(save_mp);       /* Handles NULL and non-NULL */
1104 #endif
1105                         freemsg(mp);
1106                         goto out;
1107                 }
1108 
1109                 ASSERT(ep->b_cont == mp || ep == mp);
1110                 ret = overlay_mux_tx(odd->odd_mux, &hdr, ep);
1111                 if (ret != 0) {
1112                         if (ret != EWOULDBLOCK) {
1113                                 /*
1114                                  * Get rid of the packets, something ELSE is
1115                                  * wrong with the socket, and we really should
1116                                  * just drop the packets for now.
1117                                  */
1118 #ifdef OVERLAY_FC_TEST
1119                                 freemsg(save_mp);
1120                                 save_mp = NULL;
1121 #endif
1122                                 freemsgchain(mp_chain);
1123                                 mp_chain = NULL;
1124                         }
1125 #ifdef OVERLAY_FC_TEST
1126                         if (save_mp != NULL) {
1127                                 /*
1128                                  * Return the dropped mp here to see how
1129                                  * upper-layer MAC reacts to it.
1130                                  */
1131                                 save_mp->b_next = mp_chain;
1132                                 mp_chain = save_mp;
1133                         }
1134 #endif
1135                         /*
1136                          * EWOULDBLOCK is a special case.  Return the rest of
1137                          * the mp_chain to MAC and have this instance be
1138                          * marked as unable to transmit.  Re-enable this
1139                          * instance when the mux's socket is able to send data
1140                          * again ("cansend" callback).
1141                          */
1142                         goto out;
1143                 }
1144 
1145                 mp = mp_chain;
1146         }
1147 
1148 out:
1149         mutex_enter(&odd->odd_lock);
1150         overlay_io_done(odd, OVERLAY_F_IN_TX);
1151         if (mp_chain != NULL) {
1152                 /* Note that we're returning an unsent chain to MAC. */
1153                 odd->odd_flags |= OVERLAY_F_TXSTOPPED;
1154         }
1155         mutex_exit(&odd->odd_lock);
1156         return (mp_chain);
1157 }
1158 
1159 /* ARGSUSED */
1160 static void
1161 overlay_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
1162 {
1163         miocnak(q, mp, 0, ENOTSUP);
1164 }
1165 
1166 /* ARGSUSED */
1167 static boolean_t
1168 overlay_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1169 {
1170         /*
1171          * Tell MAC we're an overlay.
1172          */
1173         if (cap == MAC_CAPAB_OVERLAY)
1174                 return (B_TRUE);