The push_header() callback of a tunnel netdev class returns void, so a tunnel implementation has no way to drop a packet it cannot encapsulate. Encrypting tunnels need this: for example, an IPsec ESP tunnel must drop packets once its sequence number space is exhausted instead of reusing a nonce.
Make push_header() return an errno value. netdev_push_header() drops packets for which it fails and counts them in the existing 'netdev_push_header_drops' coverage counter. All existing implementations always succeed. Assisted-by: claude-opus-5-5, Claude Code Signed-off-by: Thilak Raj Surendra Babu <[email protected]> --- lib/netdev-native-tnl.c | 20 +++++++++++++++----- lib/netdev-native-tnl.h | 10 +++++----- lib/netdev-provider.h | 13 ++++++++----- lib/netdev.c | 18 ++++++++++++------ 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c index f27b8b692..cf3989d1e 100644 --- a/lib/netdev-native-tnl.c +++ b/lib/netdev-native-tnl.c @@ -300,7 +300,7 @@ tnl_ol_pop(struct dp_packet *packet, int off) dp_packet_reset_packet(packet, off); } -void +int netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED, const struct netdev *ingress_netdev, struct dp_packet *packet, @@ -339,6 +339,8 @@ netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED, if (l4_ofs != UINT16_MAX) { packet->inner_l4_ofs = l4_ofs + data->header_len; } + + return 0; } static void * @@ -535,7 +537,7 @@ err: return NULL; } -void +int netdev_gre_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev OVS_UNUSED, struct dp_packet *packet, @@ -577,6 +579,8 @@ netdev_gre_push_header(const struct netdev *netdev, if (l4_ofs != UINT16_MAX) { packet->inner_l4_ofs = l4_ofs + data->header_len; } + + return 0; } int @@ -699,7 +703,7 @@ err: return NULL; } -void +int netdev_erspan_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev OVS_UNUSED, struct dp_packet *packet, @@ -724,6 +728,8 @@ netdev_erspan_push_header(const struct netdev *netdev, md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1); put_16aligned_be32(&md2->timestamp, get_erspan_ts(ERSPAN_100US)); } + + return 0; } int @@ -873,7 +879,7 @@ err: return NULL; } -void +int netdev_gtpu_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev OVS_UNUSED, struct dp_packet *packet, @@ -907,6 +913,8 @@ netdev_gtpu_push_header(const struct netdev *netdev, payload_len += sizeof(struct gtpuhdr_opt); } gtpuh->len = htons(payload_len); + + return 0; } int @@ -1007,7 +1015,7 @@ netdev_srv6_build_header(const struct netdev *netdev, return 0; } -void +int netdev_srv6_push_header(const struct netdev *netdev OVS_UNUSED, const struct netdev *ingress_netdev OVS_UNUSED, struct dp_packet *packet, @@ -1041,6 +1049,8 @@ netdev_srv6_push_header(const struct netdev *netdev OVS_UNUSED, netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size, ipv6_label); + + return 0; } struct dp_packet * diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h index ec1531d55..75430c765 100644 --- a/lib/netdev-native-tnl.h +++ b/lib/netdev-native-tnl.h @@ -33,7 +33,7 @@ netdev_gre_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, const struct netdev_tnl_build_header_params *params); -void +int netdev_gre_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev, struct dp_packet *packet, @@ -46,7 +46,7 @@ netdev_erspan_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data, const struct netdev_tnl_build_header_params *p); -void +int netdev_erspan_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev, struct dp_packet *packet, @@ -57,7 +57,7 @@ netdev_erspan_pop_header(struct dp_packet *packet); struct dp_packet * netdev_gtpu_pop_header(struct dp_packet *packet); -void +int netdev_gtpu_push_header(const struct netdev *netdev, const struct netdev *ingress_netdev, struct dp_packet *packet, @@ -70,7 +70,7 @@ netdev_gtpu_build_header(const struct netdev *netdev, struct dp_packet *netdev_srv6_pop_header(struct dp_packet *); -void netdev_srv6_push_header(const struct netdev *, +int netdev_srv6_push_header(const struct netdev *, const struct netdev *ingress_netdev, struct dp_packet *, const struct ovs_action_push_tnl *); @@ -79,7 +79,7 @@ int netdev_srv6_build_header(const struct netdev *, struct ovs_action_push_tnl *, const struct netdev_tnl_build_header_params *); -void +int netdev_tnl_push_udp_header(const struct netdev *netdev, const struct netdev *ingress_netdev, struct dp_packet *packet, diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 8646f467d..4a2423a55 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -340,11 +340,14 @@ struct netdev_class { * * The 'ingress_netdev' points to the original ingress netdev for the * 'packet'. This variable is valid only if hardware offload is enabled; - * otherwise, it will be NULL. */ - void (*push_header)(const struct netdev *netdev, - const struct netdev *ingress_netdev, - struct dp_packet *packet, - const struct ovs_action_push_tnl *data); + * otherwise, it will be NULL. + * + * Returns 0 if successful, otherwise a positive errno value. On failure + * the caller drops 'packet'. */ + int (*push_header)(const struct netdev *netdev, + const struct netdev *ingress_netdev, + struct dp_packet *packet, + const struct ovs_action_push_tnl *data); /* Pop tunnel header from packet, build tunnel metadata and resize packet * for further processing. diff --git a/lib/netdev.c b/lib/netdev.c index 533c1eadf..ba7505122 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -916,12 +916,11 @@ netdev_push_header(const struct netdev *netdev, || (data->tnl_type == OVS_VPORT_TYPE_VXLAN) || (data->tnl_type == OVS_VPORT_TYPE_GRE) || (data->tnl_type == OVS_VPORT_TYPE_IP6GRE); + size_t i, size = dp_packet_batch_size(batch); struct dp_packet *packet; if (userspace_tso_enabled()) { if (OVS_UNLIKELY(!supported_offloads)) { - size_t i, size = dp_packet_batch_size(batch); - DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) { if (OVS_UNLIKELY(dp_packet_get_tso_segsz(packet))) { COVERAGE_INC(netdev_push_header_drops); @@ -935,7 +934,7 @@ netdev_push_header(const struct netdev *netdev, dp_packet_batch_add(batch, packet); } } else { - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + DP_PACKET_BATCH_FOR_EACH (j, packet, batch) { if (dp_packet_tunnel(packet) && dp_packet_get_tso_segsz(packet)) { dp_packet_gso_batch(batch); @@ -945,13 +944,20 @@ netdev_push_header(const struct netdev *netdev, } } - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + size = dp_packet_batch_size(batch); + DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) { if (!supported_offloads || dp_packet_tunnel(packet)) { dp_packet_ol_send_prepare(packet, 0); } - netdev->netdev_class->push_header(netdev, ingress_netdev, packet, - data); + if (OVS_UNLIKELY(netdev->netdev_class->push_header(netdev, + ingress_netdev, + packet, data))) { + COVERAGE_INC(netdev_push_header_drops); + dp_packet_delete(packet); + continue; + } pkt_metadata_init(&packet->md, data->out_port); + dp_packet_batch_add(batch, packet); } return 0; -- 2.43.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
