Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148561034
D26691.id77919.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D26691.id77919.diff
View Options
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, ¶ms));
+}
+#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
Details
Attached
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)
Attached To
Mode
D26691: Support hardware rate limiting (pacing) with TLS offload.
Attached
Detach File
Event Timeline
Log In to Comment