Page MenuHomeFreeBSD

D26691.id77919.diff
No OneTemporary

D26691.id77919.diff

Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8
+++ sbin/ifconfig/ifconfig.8
@@ -561,6 +561,10 @@
.Xr ip 4
and
.Xr ip6 4 .
+.It Cm txtlsrtlmt
+Enable use of rate limiting (packet pacing) for TLS offload.
+.It Fl txtlsrtlmt
+Disable use of rate limiting for TLS offload.
.It Cm nomap
If the driver supports unmapped network buffers,
enable them on the interface.
Index: sbin/ifconfig/ifconfig.c
===================================================================
--- sbin/ifconfig/ifconfig.c
+++ sbin/ifconfig/ifconfig.c
@@ -1345,7 +1345,7 @@
"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
"\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \
"\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \
-"\36VXLAN_HWCSUM\37VXLAN_HWTSO"
+"\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT"
/*
* Print the status of the interface. If an address family was
@@ -1685,6 +1685,8 @@
DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap),
DEF_CMD("txrtlmt", IFCAP_TXRTLMT, setifcap),
DEF_CMD("-txrtlmt", -IFCAP_TXRTLMT, setifcap),
+ DEF_CMD("txtlsrtlmt", IFCAP_TXTLS_RTLMT, setifcap),
+ DEF_CMD("-txtlsrtlmt", -IFCAP_TXTLS_RTLMT, setifcap),
DEF_CMD("hwrxtstmp", IFCAP_HWRXTSTMP, setifcap),
DEF_CMD("-hwrxtstmp", -IFCAP_HWRXTSTMP, setifcap),
DEF_CMD("normal", -IFF_LINK0, setifflags),
Index: sys/dev/mlx5/mlx5_en/mlx5_en_main.c
===================================================================
--- sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -3349,6 +3349,10 @@
ifp->if_capenable ^= IFCAP_TXTLS4;
if (mask & IFCAP_TXTLS6)
ifp->if_capenable ^= IFCAP_TXTLS6;
+#ifdef RATELIMIT
+ if (mask & IFCAP_TXTLS_RTLMT)
+ ifp->if_capenable ^= IFCAP_TXTLS_RTLMT;
+#endif
if (mask & IFCAP_RXCSUM)
ifp->if_capenable ^= IFCAP_RXCSUM;
if (mask & IFCAP_RXCSUM_IPV6)
@@ -4320,7 +4324,9 @@
ifp->if_capabilities |= IFCAP_HWSTATS | IFCAP_HWRXTSTMP;
ifp->if_capabilities |= IFCAP_NOMAP;
ifp->if_capabilities |= IFCAP_TXTLS4 | IFCAP_TXTLS6;
- ifp->if_capabilities |= IFCAP_TXRTLMT;
+#ifdef RATELIMIT
+ ifp->if_capabilities |= IFCAP_TXRTLMT | IFCAP_TXTLS_RTLMT;
+#endif
ifp->if_snd_tag_alloc = mlx5e_snd_tag_alloc;
ifp->if_snd_tag_free = mlx5e_snd_tag_free;
ifp->if_snd_tag_modify = mlx5e_snd_tag_modify;
Index: sys/kern/uipc_ktls.c
===================================================================
--- sys/kern/uipc_ktls.c
+++ sys/kern/uipc_ktls.c
@@ -763,13 +763,15 @@
* the connection is currently routed over.
*/
static int
-ktls_alloc_snd_tag(struct inpcb *inp, struct ktls_session *tls, bool force,
- struct m_snd_tag **mstp)
+ktls_alloc_snd_tag(struct inpcb *inp, struct ktls_session *tls,
+ struct m_snd_tag *old, struct m_snd_tag **mstp)
{
union if_snd_tag_alloc_params params;
+ union if_snd_tag_query_params query;
struct ifnet *ifp;
struct nhop_object *nh;
struct tcpcb *tp;
+ bool have_rate;
int error;
INP_RLOCK(inp);
@@ -791,10 +793,10 @@
* Check administrative controls on ifnet TLS to determine if
* ifnet TLS should be denied.
*
- * - Always permit 'force' requests.
+ * - Always permit requests to replace an existing tag.
* - ktls_ifnet_permitted == 0: always deny.
*/
- if (!force && ktls_ifnet_permitted == 0) {
+ if (old == NULL && ktls_ifnet_permitted == 0) {
INP_RUNLOCK(inp);
return (ENXIO);
}
@@ -814,12 +816,39 @@
ifp = nh->nh_ifp;
if_ref(ifp);
- params.hdr.type = IF_SND_TAG_TYPE_TLS;
+ /*
+ * If there is an existing TLS + ratelimit tag, query it
+ * for the current rate.
+ *
+ * Otherwise, if a ratelimit tag is present on the inp,
+ * query the current rate from the inp.
+ *
+ * XXX: Should we fail if we can't query the rate?
+ *
+ * XXX: Ok to hold the inp lock for this?
+ */
+ have_rate = false;
+ if (old != NULL && old->type == IF_SND_TAG_TYPE_TLS_RATE_LIMIT &&
+ old->ifp->if_snd_tag_query(old, &query) == 0)
+ have_rate = true;
+ else if (inp->inp_snd_tag != NULL &&
+ inp->inp_snd_tag->type == IF_SND_TAG_TYPE_RATE_LIMIT &&
+ inp->inp_snd_tag->ifp->if_snd_tag_query(inp->inp_snd_tag,
+ &query) == 0)
+ have_rate = true;
+ if (have_rate && (ifp->if_capenable & IFCAP_TXTLS_RTLMT) != 0) {
+ params.hdr.type = IF_SND_TAG_TYPE_TLS_RATE_LIMIT;
+ params.tls_rate_limit.inp = inp;
+ params.tls_rate_limit.tls = tls;
+ params.tls_rate_limit.max_rate = query.rate_limit.max_rate;
+ } else {
+ params.hdr.type = IF_SND_TAG_TYPE_TLS;
+ params.tls.inp = inp;
+ params.tls.tls = tls;
+ }
params.hdr.flowid = inp->inp_flowid;
params.hdr.flowtype = inp->inp_flowtype;
params.hdr.numa_domain = inp->inp_numa_domain;
- params.tls.inp = inp;
- params.tls.tls = tls;
INP_RUNLOCK(inp);
if (ifp->if_snd_tag_alloc == NULL) {
@@ -853,7 +882,7 @@
struct m_snd_tag *mst;
int error;
- error = ktls_alloc_snd_tag(so->so_pcb, tls, force, &mst);
+ error = ktls_alloc_snd_tag(so->so_pcb, tls, NULL, &mst);
if (error == 0) {
tls->mode = TCP_TLS_MODE_IFNET;
tls->snd_tag = mst;
@@ -1034,6 +1063,7 @@
ktls_enable_tx(struct socket *so, struct tls_enable *en)
{
struct ktls_session *tls;
+ struct inpcb *inp;
int error;
if (!ktls_offload_enable)
@@ -1086,12 +1116,20 @@
return (error);
}
+ /*
+ * Write lock the INP when setting sb_tls_info so that
+ * routines in tcp_ratelimit.c can read sb_tls_info while
+ * holding the INP lock.
+ */
+ inp = so->so_pcb;
+ INP_WLOCK(inp);
SOCKBUF_LOCK(&so->so_snd);
so->so_snd.sb_tls_seqno = be64dec(en->rec_seq);
so->so_snd.sb_tls_info = tls;
if (tls->mode != TCP_TLS_MODE_SW)
so->so_snd.sb_flags |= SB_TLS_IFNET;
SOCKBUF_UNLOCK(&so->so_snd);
+ INP_WUNLOCK(inp);
sbunlock(&so->so_snd);
counter_u64_add(ktls_offload_total, 1);
@@ -1274,7 +1312,7 @@
if (old != NULL)
m_snd_tag_rele(old);
- error = ktls_alloc_snd_tag(inp, tls, true, &new);
+ error = ktls_alloc_snd_tag(inp, tls, old, &new);
if (error == 0) {
INP_WLOCK(inp);
@@ -1344,6 +1382,31 @@
mtx_pool_unlock(mtxpool_sleep, tls);
return (ENOBUFS);
}
+
+#ifdef RATELIMIT
+int
+ktls_modify_txrtlmt(struct ktls_session *tls, uint64_t max_pacing_rate)
+{
+ union if_snd_tag_modify_params params = {
+ .rate_limit.max_rate = max_pacing_rate,
+ .rate_limit.flags = M_NOWAIT,
+ };
+ struct m_snd_tag *mst;
+ struct ifnet *ifp;
+ int error;
+
+ /* Can't get to the inp, but it should be locked. */
+ /* INP_LOCK_ASSERT(inp); */
+
+ MPASS(tls->mode == TCP_TLS_MODE_IFNET);
+ MPASS(tls->snd_tag != NULL);
+ MPASS(tls->snd_tag->type == IF_SND_TAG_TYPE_TLS_RATE_LIMIT);
+
+ mst = tls->snd_tag;
+ ifp = mst->ifp;
+ return (ifp->if_snd_tag_modify(mst, &params));
+}
+#endif
#endif
void
Index: sys/net/if.h
===================================================================
--- sys/net/if.h
+++ sys/net/if.h
@@ -250,6 +250,7 @@
#define IFCAP_TXTLS6 0x10000000 /* can do TLS encryption and segmentation for TCP6 */
#define IFCAP_VXLAN_HWCSUM 0x20000000 /* can do IFCAN_HWCSUM on VXLANs */
#define IFCAP_VXLAN_HWTSO 0x40000000 /* can do IFCAP_TSO on VXLANs */
+#define IFCAP_TXTLS_RTLMT 0x80000000 /* can do TLS with rate limiting */
#define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6)
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -191,7 +191,8 @@
#define IF_SND_TAG_TYPE_RATE_LIMIT 0
#define IF_SND_TAG_TYPE_UNLIMITED 1
#define IF_SND_TAG_TYPE_TLS 2
-#define IF_SND_TAG_TYPE_MAX 3
+#define IF_SND_TAG_TYPE_TLS_RATE_LIMIT 3
+#define IF_SND_TAG_TYPE_MAX 4
struct if_snd_tag_alloc_header {
uint32_t type; /* send tag type, see IF_SND_TAG_XXX */
@@ -213,6 +214,13 @@
const struct ktls_session *tls;
};
+struct if_snd_tag_alloc_tls_rate_limit {
+ struct if_snd_tag_alloc_header hdr;
+ struct inpcb *inp;
+ const struct ktls_session *tls;
+ uint64_t max_rate; /* in bytes/s */
+};
+
struct if_snd_tag_rate_limit_params {
uint64_t max_rate; /* in bytes/s */
uint32_t queue_level; /* 0 (empty) .. 65535 (full) */
@@ -226,16 +234,19 @@
struct if_snd_tag_alloc_rate_limit rate_limit;
struct if_snd_tag_alloc_rate_limit unlimited;
struct if_snd_tag_alloc_tls tls;
+ struct if_snd_tag_alloc_tls_rate_limit tls_rate_limit;
};
union if_snd_tag_modify_params {
struct if_snd_tag_rate_limit_params rate_limit;
struct if_snd_tag_rate_limit_params unlimited;
+ struct if_snd_tag_rate_limit_params tls_rate_limit;
};
union if_snd_tag_query_params {
struct if_snd_tag_rate_limit_params rate_limit;
struct if_snd_tag_rate_limit_params unlimited;
+ struct if_snd_tag_rate_limit_params tls_rate_limit;
};
/* Query return flags */
Index: sys/net/if_vlan.c
===================================================================
--- sys/net/if_vlan.c
+++ sys/net/if_vlan.c
@@ -1781,10 +1781,10 @@
* this ever changes, then a new IFCAP_VLAN_TXTLS can be
* defined.
*/
- if (p->if_capabilities & IFCAP_TXTLS)
- cap |= p->if_capabilities & IFCAP_TXTLS;
- if (p->if_capenable & IFCAP_TXTLS)
- ena |= mena & IFCAP_TXTLS;
+ if (p->if_capabilities & (IFCAP_TXTLS | IFCAP_TXTLS_RTLMT))
+ cap |= p->if_capabilities & (IFCAP_TXTLS | IFCAP_TXTLS_RTLMT);
+ if (p->if_capenable & (IFCAP_TXTLS | IFCAP_TXTLS_RTLMT))
+ ena |= mena & (IFCAP_TXTLS | IFCAP_TXTLS_RTLMT);
ifp->if_capabilities = cap;
ifp->if_capenable = ena;
Index: sys/netinet/tcp_ratelimit.c
===================================================================
--- sys/netinet/tcp_ratelimit.c
+++ sys/netinet/tcp_ratelimit.c
@@ -1219,6 +1219,9 @@
uint64_t bytes_per_sec, int flags, int *error)
{
const struct tcp_hwrate_limit_table *rte;
+#ifdef KERN_TLS
+ struct ktls_session *tls;
+#endif
if (tp->t_inpcb->inp_snd_tag == NULL) {
/*
@@ -1231,17 +1234,30 @@
return (NULL);
}
#ifdef KERN_TLS
+ tls = NULL;
if (tp->t_inpcb->inp_socket->so_snd.sb_flags & SB_TLS_IFNET) {
- /*
- * We currently can't do both TLS and hardware
- * pacing
- */
- if (error)
- *error = EINVAL;
- return (NULL);
+ tls = tp->t_inpcb->inp_socket->so_snd.sb_tls_info;
+
+ if ((ifp->if_capenable & IFCAP_TXTLS_RTLMT) == 0 ||
+ tls->mode != TCP_TLS_MODE_IFNET) {
+ if (error)
+ *error = ENODEV;
+ return (NULL);
+ }
}
#endif
rte = rt_setup_rate(tp->t_inpcb, ifp, bytes_per_sec, flags, error);
+#ifdef KERN_TLS
+ if (rte != NULL && tls != NULL && tls->snd_tag != NULL) {
+ /*
+ * Fake a route change error to reset the TLS
+ * send tag. This will convert the existing
+ * tag to a TLS ratelimit tag.
+ */
+ MPASS(tls->snd_tag->type == IF_SND_TAG_TYPE_TLS);
+ ktls_output_eagain(tp->t_inpcb, tls);
+ }
+#endif
} else {
/*
* We are modifying a rate, wrong interface?
@@ -1261,11 +1277,45 @@
{
const struct tcp_hwrate_limit_table *nrte;
const struct tcp_rate_set *rs;
+#ifdef KERN_TLS
+ struct ktls_session *tls = NULL;
+#endif
int is_indirect = 0;
int err;
- if ((tp->t_inpcb->inp_snd_tag == NULL) ||
- (crte == NULL)) {
+ if (crte == NULL) {
+ /* Wrong interface */
+ if (error)
+ *error = EINVAL;
+ return (NULL);
+ }
+
+#ifdef KERN_TLS
+ if (tp->t_inpcb->inp_socket->so_snd.sb_flags & SB_TLS_IFNET) {
+ tls = tp->t_inpcb->inp_socket->so_snd.sb_tls_info;
+ MPASS(tls->mode == TCP_TLS_MODE_IFNET);
+ if (tls->snd_tag == NULL) {
+ /*
+ * Resetting send tag, fall through to
+ * updating the inp send tag if it exists. If
+ * it doesn't, we will just lose this rate
+ * change.
+ */
+ tls = NULL;
+ } else if (tls->snd_tag->type !=
+ IF_SND_TAG_TYPE_TLS_RATE_LIMIT) {
+ /*
+ * NIC probably doesn't support ratelimit TLS
+ * tags if it didn't allocate one when an
+ * existing rate was present, so ignore.
+ */
+ if (error)
+ *error = EOPNOTSUPP;
+ return (NULL);
+ }
+ }
+#endif
+ if (tp->t_inpcb->inp_snd_tag == NULL) {
/* Wrong interface */
if (error)
*error = EINVAL;
@@ -1322,6 +1372,11 @@
return (NULL);
}
/* Change rates to our new entry */
+#ifdef KERN_TLS
+ if (tls != NULL)
+ err = ktls_modify_txrtlmt(tls, nrte->rate);
+ else
+#endif
err = in_pcbmodify_txrtlmt(tp->t_inpcb, nrte->rate);
if (err) {
if (error)
@@ -1356,6 +1411,13 @@
rs_defer_destroy(rs);
mtx_unlock(&rs_mtx);
}
+
+ /*
+ * XXX: If this connection is using ifnet TLS, should we
+ * switch it to using an unlimited rate, or perhaps use
+ * ktls_output_eagain() to reset the send tag to a plain
+ * TLS tag?
+ */
in_pcbdetach_txrtlmt(tp->t_inpcb);
}
Index: sys/sys/ktls.h
===================================================================
--- sys/sys/ktls.h
+++ sys/sys/ktls.h
@@ -222,6 +222,9 @@
int ktls_set_tx_mode(struct socket *so, int mode);
int ktls_get_tx_mode(struct socket *so);
int ktls_output_eagain(struct inpcb *inp, struct ktls_session *tls);
+#ifdef RATELIMIT
+int ktls_modify_txrtlmt(struct ktls_session *tls, uint64_t max_pacing_rate);
+#endif
static inline struct ktls_session *
ktls_hold(struct ktls_session *tls)

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 19, 6:32 PM (5 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29973863
Default Alt Text
D26691.id77919.diff (12 KB)

Event Timeline