@@ -699,6 +699,24 @@ dp_packet_size(const struct dp_packet *b)
return b->mbuf.pkt_len;
}
+static inline uint16_t
+dp_packet_nb_segs(const struct dp_packet *b)
+{
+ return b->mbuf.nb_segs;
+}
+
+static inline uint16_t
+dp_packet_data_size(const struct dp_packet *b)
+{
+ return b->mbuf.data_len;
+}
+
+static inline struct dp_packet *
+dp_packet_next(const struct dp_packet *b )
+{
+ return (struct dp_packet *)(b->mbuf.next);
+}
+
static inline void
dp_packet_set_size(struct dp_packet *b, uint32_t v)
{
@@ -778,6 +796,27 @@ dp_packet_size(const struct dp_packet *b)
return b->size_;
}
+static inline uint16_t
+dp_packet_nb_segs(const struct dp_packet *b)
+{
+ return 1;
+}
+
+static inline struct dp_packet *
+dp_packet_next(const struct dp_packet *b )
+{
+ return NULL;
+}
+
+/*
+ only for compile
+*/
+static inline uint16_t
+dp_packet_data_size(const struct dp_packet *b)
+{
+ return b->size_;
+}
+
static inline void
dp_packet_set_size(struct dp_packet *b, uint32_t v)
{
@@ -1690,8 +1690,32 @@ netdev_linux_tap_batch_send(struct netdev *netdev_, int mtu,
size = dp_packet_size(packet);
do {
- retval = write(netdev->tap_fd, dp_packet_data(packet), size);
- error = retval < 0 ? errno : 0;
+ if (dp_packet_nb_segs(packet) > 1) {
+ int data_size = 0;
+ struct dp_packet *tmp_packet = packet;
+ void *buf = NULL;
+
+ while (tmp_packet) {
+ data_size += dp_packet_data_size(tmp_packet);
+ tmp_packet = dp_packet_next(tmp_packet);
+ }
+
+ buf = xmalloc(data_size);
+ data_size = 0;
+ while (packet) {
+ memcpy(buf + data_size,
+ dp_packet_data(packet),
+ dp_packet_data_size(packet));
+ data_size += dp_packet_data_size(packet);
+ packet = dp_packet_next(packet);
+ }
+ retval = write(netdev->tap_fd, buf, data_size);
+ error = retval < 0 ? errno : 0;
+ free(buf);
+ } else {
+ retval = write(netdev->tap_fd, dp_packet_data(packet), size);
+ error = retval < 0 ? errno : 0;
+ }
} while (error == EINTR);
if (error) {
When sending a packet with multiple segments, we use the length of the entire message as the transmission length and the base address of the first segment as the base address for the entire message. As a result, the packet sent to the network device is incorrect, containing only the content of the first segment. Fixes: d19cf8bb798ff ("Replace sendmsg with sendmmsg in netdev_linux_send") Signed-off-by: Sunyang Wu <sunyang.wu@jaguarmicro.com> --- lib/dp-packet.h | 39 +++++++++++++++++++++++++++++++++++++++ lib/netdev-linux.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 2 deletions(-)