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);
|