Author: ae
Date: Wed Oct 21 15:01:33 2020
New Revision: 366908
URL: https://svnweb.freebsd.org/changeset/base/366908

Log:
  Add dtrace SDT probe ipfw:::rule-matched.
  
  It helps to reduce complexity with debugging of large ipfw rulesets.
  Also define several constants and translators, that can by used by
  dtrace scripts with this probe.
  
  Reviewed by:  gnn
  Obtained from:        Yandex LLC
  MFC after:    2 weeks
  Sponsored by: Yandex LLC
  Differential Revision:        https://reviews.freebsd.org/D26879

Added:
  head/share/dtrace/ipfw.d   (contents, props changed)
Modified:
  head/share/dtrace/Makefile
  head/sys/netpfil/ipfw/ip_fw2.c

Modified: head/share/dtrace/Makefile
==============================================================================
--- head/share/dtrace/Makefile  Wed Oct 21 05:57:25 2020        (r366907)
+++ head/share/dtrace/Makefile  Wed Oct 21 15:01:33 2020        (r366908)
@@ -21,7 +21,7 @@ SCRIPTS=      blocking \
 
 SCRIPTSDIR= ${SHAREDIR}/dtrace
 
-DSRCS=         mbuf.d
+DSRCS=         mbuf.d ipfw.d
 
 FILES=         ${DSRCS}
 FILESDIR=      /usr/lib/dtrace

Added: head/share/dtrace/ipfw.d
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/share/dtrace/ipfw.d    Wed Oct 21 15:01:33 2020        (r366908)
@@ -0,0 +1,219 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Yandex LLC
+ * Copyright (c) 2020 Andrey V. Elsukov <a...@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#pragma D depends_on provider ipfw
+
+/* ipfw_chk() return values */
+#pragma D binding "1.0" IP_FW_PASS
+inline int IP_FW_PASS =        0;
+#pragma D binding "1.0" IP_FW_DENY
+inline int IP_FW_DENY =        1;
+#pragma D binding "1.0" IP_FW_DIVERT
+inline int IP_FW_DIVERT =      2;
+#pragma D binding "1.0" IP_FW_TEE
+inline int IP_FW_TEE =         3;
+#pragma D binding "1.0" IP_FW_DUMMYNET
+inline int IP_FW_DUMMYNET =    4;
+#pragma D binding "1.0" IP_FW_NETGRAPH
+inline int IP_FW_NETGRAPH =    5;
+#pragma D binding "1.0" IP_FW_NGTEE
+inline int IP_FW_NGTEE =       6;
+#pragma D binding "1.0" IP_FW_NAT
+inline int IP_FW_NAT =         7;
+#pragma D binding "1.0" IP_FW_REASS
+inline int IP_FW_REASS =       8;
+#pragma D binding "1.0" IP_FW_NAT64
+inline int IP_FW_NAT64 =       9;
+
+#pragma D binding "1.0" ipfw_retcodes
+inline string ipfw_retcodes[int ret] =
+       ret == IP_FW_PASS ? "PASS" :
+       ret == IP_FW_DENY ? "DENY" :
+       ret == IP_FW_DIVERT ? "DIVERT" :
+       ret == IP_FW_TEE ? "TEE" :
+       ret == IP_FW_DUMMYNET ? "DUMMYNET" :
+       ret == IP_FW_NETGRAPH ? "NETGRAPH" :
+       ret == IP_FW_NGTEE ? "NGTEE" :
+       ret == IP_FW_NAT ? "NAT" :
+       ret == IP_FW_REASS ? "REASS" :
+       ret == IP_FW_NAT64 ? "NAT64" :
+       "<unknown>";
+
+/* ip_fw_args flags */
+#pragma D binding "1.0" IPFW_ARGS_ETHER
+inline int IPFW_ARGS_ETHER =   0x00010000; /* valid ethernet header */
+#pragma D binding "1.0" IPFW_ARGS_NH4
+inline int IPFW_ARGS_NH4 =     0x00020000; /* IPv4 next hop in hopstore */
+#pragma D binding "1.0" IPFW_ARGS_NH6
+inline int IPFW_ARGS_NH6 =     0x00040000; /* IPv6 next hop in hopstore */
+#pragma D binding "1.0" IPFW_ARGS_NH4PTR
+inline int IPFW_ARGS_NH4PTR =  0x00080000; /* IPv4 next hop in next_hop */
+#pragma D binding "1.0" IPFW_ARGS_NH6PTR
+inline int IPFW_ARGS_NH6PTR =  0x00100000; /* IPv6 next hop in next_hop6 */
+#pragma D binding "1.0" IPFW_ARGS_REF
+inline int IPFW_ARGS_REF =     0x00200000; /* valid ipfw_rule_ref      */
+#pragma D binding "1.0" IPFW_ARGS_IN
+inline int IPFW_ARGS_IN =      0x00400000; /* called on input */
+#pragma D binding "1.0" IPFW_ARGS_OUT  
+inline int IPFW_ARGS_OUT =     0x00800000; /* called on output */
+#pragma D binding "1.0" IPFW_ARGS_IP4
+inline int IPFW_ARGS_IP4 =     0x01000000; /* belongs to v4 ISR */
+#pragma D binding "1.0" IPFW_ARGS_IP6
+inline int IPFW_ARGS_IP6 =     0x02000000; /* belongs to v6 ISR */
+#pragma D binding "1.0" IPFW_ARGS_DROP
+inline int IPFW_ARGS_DROP =    0x04000000; /* drop it (dummynet) */
+#pragma D binding "1.0" IPFW_ARGS_LENMASK
+inline int IPFW_ARGS_LENMASK = 0x0000ffff; /* length of data in *mem */
+
+/* ipfw_rule_ref.info */
+#pragma D binding "1.0" IPFW_INFO_MASK
+inline int IPFW_INFO_MASK =    0x0000ffff;
+#pragma D binding "1.0" IPFW_INFO_OUT
+inline int IPFW_INFO_OUT =     0x00000000;
+#pragma D binding "1.0" IPFW_INFO_IN
+inline int IPFW_INFO_IN =      0x80000000;
+#pragma D binding "1.0" IPFW_ONEPASS
+inline int IPFW_ONEPASS =      0x40000000;
+#pragma D binding "1.0" IPFW_IS_MASK
+inline int IPFW_IS_MASK =      0x30000000;
+#pragma D binding "1.0" IPFW_IS_DIVERT
+inline int IPFW_IS_DIVERT =    0x20000000;
+#pragma D binding "1.0" IPFW_IS_DUMMYNET
+inline int IPFW_IS_DUMMYNET =  0x10000000;
+#pragma D binding "1.0" IPFW_IS_PIPE
+inline int IPFW_IS_PIPE =      0x08000000;
+
+typedef struct ipfw_match_info {
+       uint32_t        flags;
+
+       struct mbuf     *m;
+       void            *mem;
+       struct inpcb    *inp;
+       struct ifnet    *ifp;
+       struct ip       *ipp;
+       struct ip6_hdr  *ip6p;
+
+       /* flow id */
+       uint8_t         addr_type;
+       uint8_t         proto;
+       uint8_t         proto_flags;
+       uint16_t        fib;    /* XXX */
+       in_addr_t       dst_ip; /* in network byte order */
+       in_addr_t       src_ip; /* in network byte order */
+       struct in6_addr dst_ip6;
+       struct in6_addr src_ip6;
+
+       uint16_t        dst_port; /* in host byte order */
+       uint16_t        src_port; /* in host byte order */
+
+       uint32_t        flowid; /* IPv6 flowid */
+       uint32_t        extra;
+
+       /* ipfw_rule_ref */
+       uint32_t        slot;
+       uint32_t        rulenum;
+       uint32_t        rule_id;
+       uint32_t        chain_id;
+       uint32_t        match_info;
+} ipfw_match_info_t;
+
+#pragma D binding "1.0" translator
+translator ipfw_match_info_t < struct ip_fw_args *p > {
+       flags =         p->flags;
+       m =             (p->flags & IPFW_ARGS_LENMASK) ? NULL : p->m;
+       mem =           (p->flags & IPFW_ARGS_LENMASK) ? p->mem : NULL;
+       inp =           p->inp;
+       ifp =           p->ifp;
+       /* Initialize IP pointer corresponding to addr_type */
+       ipp =           (p->flags & IPFW_ARGS_IP4) ?
+           (p->flags & IPFW_ARGS_LENMASK) ? (struct ip *)p->mem :
+           (p->m != NULL) ? (struct ip *)p->m->m_data : NULL : NULL;
+       ip6p =          (p->flags & IPFW_ARGS_IP6) ?
+           (p->flags & IPFW_ARGS_LENMASK) ? (struct ip6_hdr *)p->mem :
+           (p->m != NULL) ? (struct ip6_hdr *)p->m->m_data : NULL : NULL;
+
+       /* fill f_id fields */
+       addr_type =     p->f_id.addr_type;
+       proto =         p->f_id.proto;
+       proto_flags =   p->f_id._flags;
+
+       /* f_id.fib keeps truncated fibnum, use mbuf's fibnum if possible */
+       fib =           p->m != NULL ? p->m->m_pkthdr.fibnum : p->f_id.fib;
+
+       /*
+        * ipfw_chk() keeps IPv4 addresses in host byte order. But for
+        * dtrace script it is useful to have them in network byte order,
+        * because inet_ntoa() uses address in network byte order.
+        */
+       dst_ip =        htonl(p->f_id.dst_ip);
+       src_ip =        htonl(p->f_id.src_ip);
+
+       dst_ip6 =       p->f_id.dst_ip6;
+       src_ip6 =       p->f_id.src_ip6;
+
+       dst_port =      p->f_id.dst_port;
+       src_port =      p->f_id.src_port;
+
+       flowid =        p->f_id.flow_id6;
+       extra =         p->f_id.extra;
+
+       /* ipfw_rule_ref */
+       slot =          (p->flags & IPFW_ARGS_REF) ? p->rule.slot : 0;
+       rulenum =       (p->flags & IPFW_ARGS_REF) ? p->rule.rulenum : 0;
+       rule_id =       (p->flags & IPFW_ARGS_REF) ? p->rule.rule_id : 0;
+       chain_id =      (p->flags & IPFW_ARGS_REF) ? p->rule.chain_id : 0;
+       match_info =    (p->flags & IPFW_ARGS_REF) ? p->rule.info : 0;
+};
+
+typedef struct ipfw_rule_info {
+       uint16_t        act_ofs;
+       uint16_t        cmd_len;
+       uint32_t        rulenum;
+       uint8_t         flags;
+       uint8_t         set;
+       uint32_t        rule_id;
+       uint32_t        cached_id;
+       uint32_t        cached_pos;
+       uint32_t        refcnt;
+} ipfw_rule_info_t;
+
+#pragma D binding "1.0" translator
+translator ipfw_rule_info_t < struct ip_fw *r > {
+       act_ofs =       r->act_ofs;
+       cmd_len =       r->cmd_len;
+       rulenum =       r->rulenum;
+       flags =         r->flags;
+       set =           r->set;
+       rule_id =       r->id;
+       cached_id =     r->cached_id;
+       cached_pos =    r->cached_pos;
+       refcnt =        r->refcnt;
+};
+

Modified: head/sys/netpfil/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw2.c      Wed Oct 21 05:57:25 2020        
(r366907)
+++ head/sys/netpfil/ipfw/ip_fw2.c      Wed Oct 21 15:01:33 2020        
(r366908)
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/rwlock.h>
 #include <sys/rmlock.h>
+#include <sys/sdt.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
@@ -106,6 +107,18 @@ __FBSDID("$FreeBSD$");
 #include <security/mac/mac_framework.h>
 #endif
 
+#define        IPFW_PROBE(probe, arg0, arg1, arg2, arg3, arg4, arg5)           
\
+    SDT_PROBE6(ipfw, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
+
+SDT_PROVIDER_DEFINE(ipfw);
+SDT_PROBE_DEFINE6(ipfw, , , rule__matched,
+    "int",                     /* retval */
+    "int",                     /* af */
+    "void *",                  /* src addr */
+    "void *",                  /* dst addr */
+    "struct ip_fw_args *",     /* args */
+    "struct ip_fw *"           /* rule */);
+
 /*
  * static variables followed by global ones.
  * All ipfw global variables are here.
@@ -3237,6 +3250,13 @@ do {                                                     
        \
                struct ip_fw *rule = chain->map[f_pos];
                /* Update statistics */
                IPFW_INC_RULE_COUNTER(rule, pktlen);
+               IPFW_PROBE(rule__matched, retval,
+                   is_ipv4 ? AF_INET : AF_INET6,
+                   is_ipv4 ? (uintptr_t)&src_ip :
+                       (uintptr_t)&args->f_id.src_ip6,
+                   is_ipv4 ? (uintptr_t)&dst_ip :
+                       (uintptr_t)&args->f_id.dst_ip6,
+                   args, rule);
        } else {
                retval = IP_FW_DENY;
                printf("ipfw: ouch!, skip past end of rules, denying packet\n");
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to