@@ -15,6 +15,8 @@ Post-v2.9.0
* Add v4/v6 fragmentation support for conntrack.
* New "ovs-appctl dpctl/ipf-set-enabled" command for userspace datapath
conntrack fragmentation support.
+ * New "ovs-appctl dpctl/ipf-set-minfragment" command for userspace
+ datapath conntrack fragmentation support.
v2.9.0 - xx xxx xxxx
--------------------
@@ -172,6 +172,14 @@ ct_dpif_ipf_change_enabled(struct dpif *dpif, bool v6, bool enable)
: EOPNOTSUPP);
}
+int
+ct_dpif_ipf_set_min_frag(struct dpif *dpif, bool v6, uint32_t min_frag)
+{
+ return (dpif->dpif_class->ipf_set_min_frag
+ ? dpif->dpif_class->ipf_set_min_frag(dpif, v6, min_frag)
+ : EOPNOTSUPP);
+}
+
void
ct_dpif_entry_uninit(struct ct_dpif_entry *entry)
{
@@ -201,6 +201,7 @@ int ct_dpif_set_maxconns(struct dpif *dpif, uint32_t maxconns);
int ct_dpif_get_maxconns(struct dpif *dpif, uint32_t *maxconns);
int ct_dpif_get_nconns(struct dpif *dpif, uint32_t *nconns);
int ct_dpif_ipf_change_enabled(struct dpif *, bool, bool);
+int ct_dpif_ipf_set_min_frag(struct dpif *, bool, uint32_t);
void ct_dpif_entry_uninit(struct ct_dpif_entry *);
void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *,
bool verbose, bool print_stats);
@@ -1784,6 +1784,44 @@ dpctl_ct_ipf_change_enabled(int argc, const char *argv[],
return error;
}
+static int
+dpctl_ct_ipf_set_min_frag(int argc, const char *argv[],
+ struct dpctl_params *dpctl_p)
+{
+ struct dpif *dpif;
+ int error = dpctl_ct_open_dp(argc, argv, dpctl_p, &dpif, 4);
+ if (!error) {
+ char v4_or_v6[3] = {0};
+ if (ovs_scan(argv[argc - 2], "%2s", v4_or_v6) &&
+ (!strncmp(v4_or_v6, "v4", 2) || !strncmp(v4_or_v6, "v6", 2))) {
+ uint32_t min_fragment;
+ if (ovs_scan(argv[argc - 1], "%"SCNu32, &min_fragment)) {
+ error = ct_dpif_ipf_set_min_frag(
+ dpif, !strncmp(v4_or_v6, "v6", 2), min_fragment);
+
+ if (!error) {
+ dpctl_print(dpctl_p,
+ "setting minimum fragment size successful");
+ } else {
+ dpctl_error(dpctl_p, error,
+ "setting minimum fragment size failed");
+ }
+ } else {
+ error = EINVAL;
+ dpctl_error(dpctl_p, error,
+ "parameter missing for minimum fragment size");
+ }
+ } else {
+ error = EINVAL;
+ dpctl_error(dpctl_p, error,
+ "parameter missing: v4 for ipv4 or v6 for ipv6");
+ }
+ dpif_close(dpif);
+ }
+
+ return error;
+}
+
/* Undocumented commands for unit testing. */
static int
@@ -2085,6 +2123,8 @@ static const struct dpctl_command all_commands[] = {
{ "ct-get-nconns", "[dp]", 0, 1, dpctl_ct_get_nconns, DP_RO },
{ "ipf-set-enabled", "[dp] v4_or_v6 enabled", 2, 3,
dpctl_ct_ipf_change_enabled, DP_RW },
+ { "ipf-set-minfragment", "[dp] v4_or_v6 minfragment", 2, 3,
+ dpctl_ct_ipf_set_min_frag, DP_RW },
{ "help", "", 0, INT_MAX, dpctl_help, DP_RO },
{ "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
@@ -279,3 +279,10 @@ differentiate between first and other fragments. Although, this would
logically happen naturally anyways, it is mentioned for clarity. If there
is a need to differentiate between first and other fragments, do it after
conntrack.
+.
+.TP
+\*(DX\fBipf\-set\-minfrag\fR [\fIdp\fR] [\fIv4 or v6\fR] \fBminfrag\fR
+Sets the minimum fragment size supported by the userspace datapath
+connection tracker. Either v4 or v6 must be specified. The default v4
+value is 1200 and the clamped minimum is 400. The default v6 value is
+1280, which is also the clamped minimum.
@@ -5879,6 +5879,13 @@ dpif_netdev_ipf_change_enabled(struct dpif *dpif OVS_UNUSED, bool v6,
return ipf_change_enabled(v6, enable);
}
+static int
+dpif_netdev_ipf_set_min_frag(struct dpif *dpif OVS_UNUSED, bool v6,
+ uint32_t min_frag)
+{
+ return ipf_set_min_frag(v6, min_frag);
+}
+
const struct dpif_class dpif_netdev_class = {
"netdev",
dpif_netdev_init,
@@ -5928,6 +5935,7 @@ const struct dpif_class dpif_netdev_class = {
dpif_netdev_ct_get_maxconns,
dpif_netdev_ct_get_nconns,
dpif_netdev_ipf_change_enabled,
+ dpif_netdev_ipf_set_min_frag,
dpif_netdev_meter_get_features,
dpif_netdev_meter_set,
dpif_netdev_meter_get,
@@ -2993,6 +2993,7 @@ const struct dpif_class dpif_netlink_class = {
NULL, /* ct_get_maxconns */
NULL, /* ct_get_nconns */
NULL, /* ipf_change_enabled */
+ NULL, /* ipf_set_min_frag */
dpif_netlink_meter_get_features,
dpif_netlink_meter_set,
dpif_netlink_meter_get,
@@ -446,6 +446,8 @@ struct dpif_class {
/* IP Fragmentation. */
int (*ipf_change_enabled)(struct dpif *, bool, bool);
+ /* Set minimum fragment allowed. */
+ int (*ipf_set_min_frag)(struct dpif *, bool, uint32_t);
/* Meters */
/* Queries 'dpif' for supported meter features.
@@ -1253,3 +1253,26 @@ ipf_change_enabled(bool v6, bool enable)
}
return 0;
}
+
+int
+ipf_set_min_frag(bool v6, uint32_t value)
+{
+ /* If the user specifies an unreasonably large number, fragmentation
+ * will not work well but it will not blow up. */
+ if ((!v6 && value < IPF_V4_FRAG_SIZE_LBOUND) ||
+ (v6 && value < IPF_V6_FRAG_SIZE_LBOUND)) {
+ return 1;
+ }
+
+ ipf_lock_lock(&ipf_lock);
+ if (v6) {
+ atomic_store_relaxed(&min_v6_frag_size, value);
+ } else {
+ atomic_store_relaxed(&min_v4_frag_size, value);
+ max_v4_frag_list_size = DIV_ROUND_UP(
+ IPV4_PACKET_MAX_SIZE - IPV4_PACKET_MAX_HDR_SIZE,
+ min_v4_frag_size - IPV4_PACKET_MAX_HDR_SIZE);
+ }
+ ipf_lock_unlock(&ipf_lock);
+ return 0;
+}
@@ -63,4 +63,7 @@ ipf_destroy(void);
int
ipf_change_enabled(bool v6, bool enable);
+int
+ipf_set_min_frag(bool v6, uint32_t value);
+
#endif /* ipf.h */
A new command "ovs-appctl dpctl/ipf-set-minfrag" is added for userspace datapath conntrack fragmentation support. Signed-off-by: Darrell Ball <dlu998@gmail.com> --- NEWS | 2 ++ lib/ct-dpif.c | 8 ++++++++ lib/ct-dpif.h | 1 + lib/dpctl.c | 40 ++++++++++++++++++++++++++++++++++++++++ lib/dpctl.man | 7 +++++++ lib/dpif-netdev.c | 8 ++++++++ lib/dpif-netlink.c | 1 + lib/dpif-provider.h | 2 ++ lib/ipf.c | 23 +++++++++++++++++++++++ lib/ipf.h | 3 +++ 10 files changed, 95 insertions(+)