After detailed verification, I found that my previous modification had issues.
Directly modifying l2_pad_size causes the calculation of the outer UDP
checksum to be incorrect. Therefore, I made another revision, adding a new
inner_l2_pad_size, which seems more reasonable. With this change,
if packets with padding smaller than 64 bytes are present, both the inner
and outer checksums validate correctly after adding tunnel encapsulation.
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index
584e1eb44f9c999fd368b7f84d05abc3c02c242b..fd64d371c23e0f08f1cc0c032f4bb69c1bd8f9a0
100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -176,6 +176,8 @@ struct dp_packet {
ovs_be32 packet_type; /* Packet type as defined in OpenFlow */
uint16_t csum_start; /* Position to start checksumming from. */
uint16_t csum_offset; /* Offset to place checksum. */
+ uint16_t inner_l2_pad_size; /* Detected inner l2 padding size.
+ * Padding is non-pullable. */
union {
struct pkt_metadata md;
uint64_t data[DP_PACKET_CONTEXT_SIZE / 8];
@@ -208,7 +210,9 @@ static inline void *dp_packet_eth(const struct dp_packet *);
static inline void dp_packet_reset_offsets(struct dp_packet *);
static inline void dp_packet_reset_offload(struct dp_packet *);
static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
+static inline uint16_t dp_packet_inner_l2_pad_size(const struct dp_packet *);
static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
+static inline void dp_packet_set_inner_l2_pad_size(struct dp_packet *,
uint16_t);
static inline void *dp_packet_l2_5(const struct dp_packet *);
static inline void dp_packet_set_l2_5(struct dp_packet *, void *);
static inline void *dp_packet_l3(const struct dp_packet *);
@@ -431,6 +435,7 @@ static inline void
dp_packet_reset_offsets(struct dp_packet *b)
{
b->l2_pad_size = 0;
+ b->inner_l2_pad_size = 0;
b->l2_5_ofs = UINT16_MAX;
b->l3_ofs = UINT16_MAX;
b->l4_ofs = UINT16_MAX;
@@ -444,6 +449,12 @@ dp_packet_l2_pad_size(const struct dp_packet *b)
return b->l2_pad_size;
}
+static inline uint16_t
+dp_packet_inner_l2_pad_size(const struct dp_packet *b)
+{
+ return b->inner_l2_pad_size;
+}
+
static inline void
dp_packet_set_l2_pad_size(struct dp_packet *b, uint16_t pad_size)
{
@@ -451,6 +462,13 @@ dp_packet_set_l2_pad_size(struct dp_packet *b, uint16_t
pad_size)
b->l2_pad_size = pad_size;
}
+static inline void
+dp_packet_set_inner_l2_pad_size(struct dp_packet *b, uint16_t pad_size)
+{
+ ovs_assert(pad_size <= dp_packet_size(b));
+ b->inner_l2_pad_size = pad_size;
+}
+
static inline void *
dp_packet_l2_5(const struct dp_packet *b)
{
@@ -539,7 +557,7 @@ dp_packet_inner_l4_size(const struct dp_packet *b)
return OVS_LIKELY(b->inner_l4_ofs != UINT16_MAX)
? (const char *) dp_packet_tail(b)
- (const char *) dp_packet_inner_l4(b)
- - dp_packet_l2_pad_size(b)
+ - dp_packet_inner_l2_pad_size(b)
: 0;
}
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index
b3f6a11afc6bfa0dc2bf08fce48196ef7a7b6368..395bdd433d268a8de482ed36ed4fab0c757e888c
100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -157,6 +157,7 @@ netdev_tnl_push_ip_header(struct dp_packet *packet,
struct eth_header *eth;
struct ip_header *ip;
struct ovs_16aligned_ip6_hdr *ip6;
+ uint16_t l2_pad_size;
eth = dp_packet_push_uninit(packet, size);
*ip_tot_size = dp_packet_size(packet) - sizeof (struct eth_header);
@@ -164,7 +165,9 @@ netdev_tnl_push_ip_header(struct dp_packet *packet,
memcpy(eth, header, size);
/* The encapsulated packet has type Ethernet. Adjust dp_packet. */
packet->packet_type = htonl(PT_ETH);
+ l2_pad_size = dp_packet_l2_pad_size(packet);
dp_packet_reset_offsets(packet);
+ dp_packet_set_inner_l2_pad_size(packet, l2_pad_size);
packet->l3_ofs = sizeof (struct eth_header);
if (netdev_tnl_is_header_ipv6(header)) {
Jun Wang
_______________________________________________
discuss mailing list
disc...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss