summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/tap.c74
1 files changed, 72 insertions, 2 deletions
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 7996ed7cbf18..a4ab4a791fe7 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -1146,14 +1146,84 @@ static const struct file_operations tap_fops = {
1146#endif 1146#endif
1147}; 1147};
1148 1148
1149static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
1150{
1151 struct tun_xdp_hdr *hdr = xdp->data_hard_start;
1152 struct virtio_net_hdr *gso = &hdr->gso;
1153 int buflen = hdr->buflen;
1154 int vnet_hdr_len = 0;
1155 struct tap_dev *tap;
1156 struct sk_buff *skb;
1157 int err, depth;
1158
1159 if (q->flags & IFF_VNET_HDR)
1160 vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
1161
1162 skb = build_skb(xdp->data_hard_start, buflen);
1163 if (!skb) {
1164 err = -ENOMEM;
1165 goto err;
1166 }
1167
1168 skb_reserve(skb, xdp->data - xdp->data_hard_start);
1169 skb_put(skb, xdp->data_end - xdp->data);
1170
1171 skb_set_network_header(skb, ETH_HLEN);
1172 skb_reset_mac_header(skb);
1173 skb->protocol = eth_hdr(skb)->h_proto;
1174
1175 if (vnet_hdr_len) {
1176 err = virtio_net_hdr_to_skb(skb, gso, tap_is_little_endian(q));
1177 if (err)
1178 goto err_kfree;
1179 }
1180
1181 skb_probe_transport_header(skb, ETH_HLEN);
1182
1183 /* Move network header to the right position for VLAN tagged packets */
1184 if ((skb->protocol == htons(ETH_P_8021Q) ||
1185 skb->protocol == htons(ETH_P_8021AD)) &&
1186 __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
1187 skb_set_network_header(skb, depth);
1188
1189 rcu_read_lock();
1190 tap = rcu_dereference(q->tap);
1191 if (tap) {
1192 skb->dev = tap->dev;
1193 dev_queue_xmit(skb);
1194 } else {
1195 kfree_skb(skb);
1196 }
1197 rcu_read_unlock();
1198
1199 return 0;
1200
1201err_kfree:
1202 kfree_skb(skb);
1203err:
1204 rcu_read_lock();
1205 tap = rcu_dereference(q->tap);
1206 if (tap && tap->count_tx_dropped)
1207 tap->count_tx_dropped(tap);
1208 rcu_read_unlock();
1209 return err;
1210}
1211
1149static int tap_sendmsg(struct socket *sock, struct msghdr *m, 1212static int tap_sendmsg(struct socket *sock, struct msghdr *m,
1150 size_t total_len) 1213 size_t total_len)
1151{ 1214{
1152 struct tap_queue *q = container_of(sock, struct tap_queue, sock); 1215 struct tap_queue *q = container_of(sock, struct tap_queue, sock);
1153 struct tun_msg_ctl *ctl = m->msg_control; 1216 struct tun_msg_ctl *ctl = m->msg_control;
1217 struct xdp_buff *xdp;
1218 int i;
1154 1219
1155 if (ctl && ctl->type != TUN_MSG_UBUF) 1220 if (ctl && (ctl->type == TUN_MSG_PTR)) {
1156 return -EINVAL; 1221 for (i = 0; i < ctl->num; i++) {
1222 xdp = &((struct xdp_buff *)ctl->ptr)[i];
1223 tap_get_user_xdp(q, xdp);
1224 }
1225 return 0;
1226 }
1157 1227
1158 return tap_get_user(q, ctl ? ctl->ptr : NULL, &m->msg_iter, 1228 return tap_get_user(q, ctl ? ctl->ptr : NULL, &m->msg_iter,
1159 m->msg_flags & MSG_DONTWAIT); 1229 m->msg_flags & MSG_DONTWAIT);