From nobody Fri May 20 12:51:17 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 3C9A61AE0BE4; Fri, 20 May 2022 12:51:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4L4RRp0dT8z3Bn4; Fri, 20 May 2022 12:51:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1653051078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=T0bIsG5DNYcZtahEOW4AA1pFqH9Ibm47KREpoRmvuf4=; b=FFPGsobEnpasGNffNJQ4aHUitRnIGrNgOPl6eI+07aXoW6P9Mh0822dbNDj47/yiWVhwrB v29RJN2YImMg8OxPqGlPTv8KeHOfRM8wAWraStHCaCsMhK1vvqRvIMKU6nGXohKA7t024N htfbOWKMuYO7ZX2Et0TBTp+cdoojtaml4NaGVqlWiPKdpvFH8Ai4EpJ7+SItvlOyDKW2SU IUHs2w69l3XKuLaUI1nREtoIBctT9cDWcD1lwF2sdZ5OkIANyb1EZ+iQUS/jpfdvl6CEBq aOeiN73HBXBN1nZoAqq56LvifQjVVzyYmHxeJdeJxFjW+sq1kL6zd81+FELKew== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E8D88124CF; Fri, 20 May 2022 12:51:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 24KCpHOE086998; Fri, 20 May 2022 12:51:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 24KCpHLp086997; Fri, 20 May 2022 12:51:17 GMT (envelope-from git) Date: Fri, 20 May 2022 12:51:17 GMT Message-Id: <202205201251.24KCpHLp086997@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: bbec8e698b5b - main - pf: call dummynet directly from the ethernet code List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: bbec8e698b5bfbd568b840fc411b4fd125684045 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1653051078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=T0bIsG5DNYcZtahEOW4AA1pFqH9Ibm47KREpoRmvuf4=; b=tr+pVHR+MgndL6SgbwSDQM/4zukao+P0QZP5MYoxtHtRYVS1iuBBdBJiL/J6M9oxHFSJuq AMC0uTsJ87SNk9te5n/HwxgxqWBlZX7mbP//Ht/hfualaQeZOQIDpzkeuwPB7Jcy/QYzh8 IgxTCQOiPsqQUCKL59WBUEMAC5ehIZaUT95pjGXuSzMNhTHMVLA+kiYfk+51MHuipWgADQ 2Ge1E1rV1fJnP9SwPkDyh2fvKSRlLm7u3eSLGwAiuZoldCXrcvZRrA6fmLuPxjg6Fz0RWV jfOc09tCBtyrfxH1c/jwQKFdLXaAbQogKJznXC2ywn8r6jgcORUYdpazByyjsw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1653051078; a=rsa-sha256; cv=none; b=k9gq6EqWPQZKDfeLVjl+psPTrFUOJT8fduwfRiS7pxKy+C3gDpPzpJV/Xy8i7weR29tSbG x++Uu/8DDi55Rziz2xzoxY96jp3+/0t9hEesHJL47X7acIxGK6OFC/IoIgfg9IAoJJcWpN auMHBycAd5tGV/gINCUNKpotPrkReCWIyt13MXkV/v0G8fOeojwgGPvDzjZIpEeo66ffGq NPB9OEcyakzz06UADkQbd8NQ7bfLn05Fdify2h0gPkykn+yjgXyl1A6Ta+tZfb64V4ldaF qIfcCKHQeugFEidQ/yqoU9Na7PL9Vd0jZZOZps0AEeAmR4Ny0q29KZXLyAZEHA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=bbec8e698b5bfbd568b840fc411b4fd125684045 commit bbec8e698b5bfbd568b840fc411b4fd125684045 Author: Kristof Provost AuthorDate: 2022-05-18 15:49:28 +0000 Commit: Kristof Provost CommitDate: 2022-05-20 12:49:31 +0000 pf: call dummynet directly from the ethernet code Until recently dummynet in ethernet rules did not send packets directly to dummynet but instead marked them and left the interactions with dummynet to the layer 3 pf code. This worked fine for incoming packets (where we process ethernet rules before layer 3 rules), but not for outbound packets (where the order of operations is the reverse). Dummynet does support handling layer 2 traffic, so send the packets directly to dummynet. The main limitation now is that pf does not inspect layer 4 (i.e. TCP/UDP) so we don't have protocol information or port numbers. Dummynet potentially uses this to separate traffic flows, which will not work for ethernet dummynet rules. However, pipes (i.e. adding latency or restricting bandwidth) will work exactly as expected. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D35257 --- sys/netpfil/pf/pf.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 5b3bc719ecb6..c613194ce9b5 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3858,6 +3858,19 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) SDT_PROBE3(pf, eth, test_rule, entry, dir, kif->pfik_ifp, m); + mtag = pf_find_mtag(m); + if (mtag != NULL && mtag->flags & PF_TAG_DUMMYNET) { + /* Dummynet re-injects packets after they've + * completed their delay. We've already + * processed them, so pass unconditionally. */ + + /* But only once. We may see the packet multiple times (e.g. + * PFIL_IN/PFIL_OUT). */ + mtag->flags &= ~PF_TAG_DUMMYNET; + + return (PF_PASS); + } + ruleset = V_pf_keth; rules = ck_pr_load_ptr(&ruleset->active.rules); r = TAILQ_FIRST(rules); @@ -3989,7 +4002,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) } if (r->tag > 0) { - mtag = pf_get_mtag(m); + if (mtag == NULL) + mtag = pf_get_mtag(m); if (mtag == NULL) { PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); @@ -3999,7 +4013,8 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) } if (r->qid != 0) { - mtag = pf_get_mtag(m); + if (mtag == NULL) + mtag = pf_get_mtag(m); if (mtag == NULL) { PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); @@ -4010,19 +4025,64 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) /* Dummynet */ if (r->dnpipe) { - /** While dummynet supports handling Ethernet packets directly - * it still wants some L3/L4 information, and we're not set up - * to provide that here. Instead we'll do what we do for ALTQ - * and merely mark the packet with the dummynet queue/pipe number. - **/ - mtag = pf_get_mtag(m); + struct ip_fw_args dnflow; + + /* Drop packet if dummynet is not loaded. */ + if (ip_dn_io_ptr == NULL) { + PF_RULES_RUNLOCK(); + m_freem(m); + counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); + return (PF_DROP); + } + if (mtag == NULL) + mtag = pf_get_mtag(m); if (mtag == NULL) { PF_RULES_RUNLOCK(); counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1); return (PF_DROP); } - mtag->dnpipe = r->dnpipe; - mtag->dnflags = r->dnflags; + + bzero(&dnflow, sizeof(dnflow)); + + /* We don't have port numbers here, so we set 0. That means + * that we'll be somewhat limited in distinguishing flows (i.e. + * only based on IP addresses, not based on port numbers), but + * it's better than nothing. */ + dnflow.f_id.dst_port = 0; + dnflow.f_id.src_port = 0; + dnflow.f_id.proto = 0; + + dnflow.rule.info = r->dnpipe; + dnflow.rule.info |= IPFW_IS_DUMMYNET; + if (r->dnflags & PFRULE_DN_IS_PIPE) + dnflow.rule.info |= IPFW_IS_PIPE; + + dnflow.f_id.extra = dnflow.rule.info; + + dnflow.flags = dir == PF_IN ? IPFW_ARGS_IN : IPFW_ARGS_OUT; + dnflow.flags |= IPFW_ARGS_ETHER; + dnflow.ifp = kif->pfik_ifp; + + switch (af) { + case AF_INET: + dnflow.f_id.addr_type = 4; + dnflow.f_id.src_ip = src->v4.s_addr; + dnflow.f_id.dst_ip = dst->v4.s_addr; + break; + case AF_INET6: + dnflow.flags |= IPFW_ARGS_IP6; + dnflow.f_id.addr_type = 6; + dnflow.f_id.src_ip6 = src->v6; + dnflow.f_id.dst_ip6 = dst->v6; + break; + default: + panic("Unknown address family"); + } + + mtag->flags |= PF_TAG_DUMMYNET; + ip_dn_io_ptr(m0, &dnflow); + if (*m0 != NULL) + mtag->flags &= ~PF_TAG_DUMMYNET; } action = r->action;