summaryrefslogtreecommitdiffstats
path: root/net/sctp/protocol.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 22:22:29 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 22:22:29 +0100
commitd635a69dd4981cc51f90293f5f64268620ed1565 (patch)
tree5e0a758b402ea7d624c25c3a343545dd29e80f31 /net/sctp/protocol.c
parentMerge branch 'akpm' (patches from Andrew) (diff)
parentnet: hns3: fix expression that is currently always true (diff)
downloadlinux-d635a69dd4981cc51f90293f5f64268620ed1565.tar.xz
linux-d635a69dd4981cc51f90293f5f64268620ed1565.zip
Merge tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Jakub Kicinski: "Core: - support "prefer busy polling" NAPI operation mode, where we defer softirq for some time expecting applications to periodically busy poll - AF_XDP: improve efficiency by more batching and hindering the adjacency cache prefetcher - af_packet: make packet_fanout.arr size configurable up to 64K - tcp: optimize TCP zero copy receive in presence of partial or unaligned reads making zero copy a performance win for much smaller messages - XDP: add bulk APIs for returning / freeing frames - sched: support fragmenting IP packets as they come out of conntrack - net: allow virtual netdevs to forward UDP L4 and fraglist GSO skbs BPF: - BPF switch from crude rlimit-based to memcg-based memory accounting - BPF type format information for kernel modules and related tracing enhancements - BPF implement task local storage for BPF LSM - allow the FENTRY/FEXIT/RAW_TP tracing programs to use bpf_sk_storage Protocols: - mptcp: improve multiple xmit streams support, memory accounting and many smaller improvements - TLS: support CHACHA20-POLY1305 cipher - seg6: add support for SRv6 End.DT4/DT6 behavior - sctp: Implement RFC 6951: UDP Encapsulation of SCTP - ppp_generic: add ability to bridge channels directly - bridge: Connectivity Fault Management (CFM) support as is defined in IEEE 802.1Q section 12.14. Drivers: - mlx5: make use of the new auxiliary bus to organize the driver internals - mlx5: more accurate port TX timestamping support - mlxsw: - improve the efficiency of offloaded next hop updates by using the new nexthop object API - support blackhole nexthops - support IEEE 802.1ad (Q-in-Q) bridging - rtw88: major bluetooth co-existance improvements - iwlwifi: support new 6 GHz frequency band - ath11k: Fast Initial Link Setup (FILS) - mt7915: dual band concurrent (DBDC) support - net: ipa: add basic support for IPA v4.5 Refactor: - a few pieces of in_interrupt() cleanup work from Sebastian Andrzej Siewior - phy: add support for shared interrupts; get rid of multiple driver APIs and have the drivers write a full IRQ handler, slight growth of driver code should be compensated by the simpler API which also allows shared IRQs - add common code for handling netdev per-cpu counters - move TX packet re-allocation from Ethernet switch tag drivers to a central place - improve efficiency and rename nla_strlcpy - number of W=1 warning cleanups as we now catch those in a patchwork build bot Old code removal: - wan: delete the DLCI / SDLA drivers - wimax: move to staging - wifi: remove old WDS wifi bridging support" * tag 'net-next-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1922 commits) net: hns3: fix expression that is currently always true net: fix proc_fs init handling in af_packet and tls nfc: pn533: convert comma to semicolon af_vsock: Assign the vsock transport considering the vsock address flags af_vsock: Set VMADDR_FLAG_TO_HOST flag on the receive path vsock_addr: Check for supported flag values vm_sockets: Add VMADDR_FLAG_TO_HOST vsock flag vm_sockets: Add flags field in the vsock address data structure net: Disable NETIF_F_HW_TLS_TX when HW_CSUM is disabled tcp: Add logic to check for SYN w/ data in tcp_simple_retransmit net: mscc: ocelot: install MAC addresses in .ndo_set_rx_mode from process context nfc: s3fwrn5: Release the nfc firmware net: vxget: clean up sparse warnings mlxsw: spectrum_router: Use eXtended mezzanine to offload IPv4 router mlxsw: spectrum: Set KVH XLT cache mode for Spectrum2/3 mlxsw: spectrum_router_xm: Introduce basic XM cache flushing mlxsw: reg: Add Router LPM Cache Enable Register mlxsw: reg: Add Router LPM Cache ML Delete Register mlxsw: spectrum_router_xm: Implement L-value tracking for M-index mlxsw: reg: Add XM Router M Table Register ...
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r--net/sctp/protocol.c142
1 files changed, 130 insertions, 12 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 25833238fe93..6f2bbfeec3a4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -44,6 +44,7 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_ecn.h>
+#include <net/udp_tunnel.h>
#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
@@ -840,6 +841,92 @@ static int sctp_ctl_sock_init(struct net *net)
return 0;
}
+static int sctp_udp_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ SCTP_INPUT_CB(skb)->encap_port = udp_hdr(skb)->source;
+
+ skb_set_transport_header(skb, sizeof(struct udphdr));
+ sctp_rcv(skb);
+ return 0;
+}
+
+static int sctp_udp_err_lookup(struct sock *sk, struct sk_buff *skb)
+{
+ struct sctp_association *asoc;
+ struct sctp_transport *t;
+ int family;
+
+ skb->transport_header += sizeof(struct udphdr);
+ family = (ip_hdr(skb)->version == 4) ? AF_INET : AF_INET6;
+ sk = sctp_err_lookup(dev_net(skb->dev), family, skb, sctp_hdr(skb),
+ &asoc, &t);
+ if (!sk)
+ return -ENOENT;
+
+ sctp_err_finish(sk, t);
+ return 0;
+}
+
+int sctp_udp_sock_start(struct net *net)
+{
+ struct udp_tunnel_sock_cfg tuncfg = {NULL};
+ struct udp_port_cfg udp_conf = {0};
+ struct socket *sock;
+ int err;
+
+ udp_conf.family = AF_INET;
+ udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
+ udp_conf.local_udp_port = htons(net->sctp.udp_port);
+ err = udp_sock_create(net, &udp_conf, &sock);
+ if (err) {
+ pr_err("Failed to create the SCTP UDP tunneling v4 sock\n");
+ return err;
+ }
+
+ tuncfg.encap_type = 1;
+ tuncfg.encap_rcv = sctp_udp_rcv;
+ tuncfg.encap_err_lookup = sctp_udp_err_lookup;
+ setup_udp_tunnel_sock(net, sock, &tuncfg);
+ net->sctp.udp4_sock = sock->sk;
+
+#if IS_ENABLED(CONFIG_IPV6)
+ memset(&udp_conf, 0, sizeof(udp_conf));
+
+ udp_conf.family = AF_INET6;
+ udp_conf.local_ip6 = in6addr_any;
+ udp_conf.local_udp_port = htons(net->sctp.udp_port);
+ udp_conf.use_udp6_rx_checksums = true;
+ udp_conf.ipv6_v6only = true;
+ err = udp_sock_create(net, &udp_conf, &sock);
+ if (err) {
+ pr_err("Failed to create the SCTP UDP tunneling v6 sock\n");
+ udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket);
+ net->sctp.udp4_sock = NULL;
+ return err;
+ }
+
+ tuncfg.encap_type = 1;
+ tuncfg.encap_rcv = sctp_udp_rcv;
+ tuncfg.encap_err_lookup = sctp_udp_err_lookup;
+ setup_udp_tunnel_sock(net, sock, &tuncfg);
+ net->sctp.udp6_sock = sock->sk;
+#endif
+
+ return 0;
+}
+
+void sctp_udp_sock_stop(struct net *net)
+{
+ if (net->sctp.udp4_sock) {
+ udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket);
+ net->sctp.udp4_sock = NULL;
+ }
+ if (net->sctp.udp6_sock) {
+ udp_tunnel_sock_release(net->sctp.udp6_sock->sk_socket);
+ net->sctp.udp6_sock = NULL;
+ }
+}
+
/* Register address family specific functions. */
int sctp_register_af(struct sctp_af *af)
{
@@ -971,25 +1058,44 @@ static int sctp_inet_supported_addrs(const struct sctp_sock *opt,
}
/* Wrapper routine that calls the ip transmit routine. */
-static inline int sctp_v4_xmit(struct sk_buff *skb,
- struct sctp_transport *transport)
+static inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t)
{
- struct inet_sock *inet = inet_sk(skb->sk);
+ struct dst_entry *dst = dst_clone(t->dst);
+ struct flowi4 *fl4 = &t->fl.u.ip4;
+ struct sock *sk = skb->sk;
+ struct inet_sock *inet = inet_sk(sk);
__u8 dscp = inet->tos;
+ __be16 df = 0;
pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb,
- skb->len, &transport->fl.u.ip4.saddr,
- &transport->fl.u.ip4.daddr);
+ skb->len, &fl4->saddr, &fl4->daddr);
- if (transport->dscp & SCTP_DSCP_SET_MASK)
- dscp = transport->dscp & SCTP_DSCP_VAL_MASK;
+ if (t->dscp & SCTP_DSCP_SET_MASK)
+ dscp = t->dscp & SCTP_DSCP_VAL_MASK;
+
+ inet->pmtudisc = t->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO
+ : IP_PMTUDISC_DONT;
+ SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
- inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
- IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
+ if (!t->encap_port || !sctp_sk(sk)->udp_port) {
+ skb_dst_set(skb, dst);
+ return __ip_queue_xmit(sk, skb, &t->fl, dscp);
+ }
- SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
+ if (skb_is_gso(skb))
+ skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
- return __ip_queue_xmit(&inet->sk, skb, &transport->fl, dscp);
+ if (ip_dont_fragment(sk, dst) && !skb->ignore_df)
+ df = htons(IP_DF);
+
+ skb->encapsulation = 1;
+ skb_reset_inner_mac_header(skb);
+ skb_reset_inner_transport_header(skb);
+ skb_set_inner_ipproto(skb, IPPROTO_SCTP);
+ udp_tunnel_xmit_skb((struct rtable *)dst, sk, skb, fl4->saddr,
+ fl4->daddr, dscp, ip4_dst_hoplimit(dst), df,
+ sctp_sk(sk)->udp_port, t->encap_port, false, false);
+ return 0;
}
static struct sctp_af sctp_af_inet;
@@ -1054,9 +1160,15 @@ static struct inet_protosw sctp_stream_protosw = {
.flags = SCTP_PROTOSW_FLAG
};
+static int sctp4_rcv(struct sk_buff *skb)
+{
+ SCTP_INPUT_CB(skb)->encap_port = 0;
+ return sctp_rcv(skb);
+}
+
/* Register with IP layer. */
static const struct net_protocol sctp_protocol = {
- .handler = sctp_rcv,
+ .handler = sctp4_rcv,
.err_handler = sctp_v4_err,
.no_policy = 1,
.netns_ok = 1,
@@ -1271,6 +1383,12 @@ static int __net_init sctp_defaults_init(struct net *net)
/* Enable ECN by default. */
net->sctp.ecn_enable = 1;
+ /* Set UDP tunneling listening port to 0 by default */
+ net->sctp.udp_port = 0;
+
+ /* Set remote encap port to 0 by default */
+ net->sctp.encap_port = 0;
+
/* Set SCOPE policy to enabled */
net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE;