]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: implement link_ntop() DTrace subroutine logic
authorGirish Moodalbail <girish.moodalbail@oracle.com>
Tue, 11 Apr 2017 00:39:14 +0000 (17:39 -0700)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 21 Apr 2017 14:44:58 +0000 (15:44 +0100)
The signature of the link_ntop() DTrace subroutine is:

    string link_ntop(int hardware_type, void *addr);

link_ntop() takes a pointer to a hardware address and returns a string
which is the translation of that address to a string representation,
with content depending on the provided hardware type.  Supported
hardware types are ARPHRD_ETHER and ARPHRD_INFINIBAND, both of which
are defined for use in D programs.

This is the link-level equivalent of inet_ntop().

Signed-off-by: Girish Moodalbail <girish.moodalbail@oracle.com>
Reviewed-by: Nick Alcock <nick.alcock@oracle.com>
[nca: reworded commit message a bit]
Orabug: 25931479

dtrace/.gitignore
dtrace/dtrace_dif.c
dtrace/include/uapi/linux/dtrace/dif_defines.h

index 008c2d4a7b161d2b77009721deec37f4b713af1f..d9e47cc0d9eca27da89a84910481845b07e89968 100644 (file)
@@ -25,3 +25,15 @@ Module.symvers
 #
 *.sdtinfo.c
 *.sdtstub.S
+
+#
+# cscope files
+#
+cscope.*
+ncscope.*
+
+#
+# Top-level tag files
+#
+/tags
+/*TAGS
index b31ec8e097f07f76c2bcdb42936f99ccbe32356f..0906c7904fdea3b1068abf7856f7679add2b9555 100644 (file)
@@ -27,6 +27,9 @@
 #include <linux/dtrace_cpu.h>
 #include <linux/fdtable.h>
 #include <linux/hardirq.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_infiniband.h>
 #include <linux/in6.h>
 #include <linux/inet.h>
 #include <linux/jiffies.h>
@@ -52,6 +55,8 @@ const char                    dtrace_zero[256] = { 0, };
 
 uint64_t                       dtrace_vtime_references;
 
+static const char              dtrace_hexdigits[] = "0123456789abcdef";
+
 static int dtrace_difo_err(uint_t pc, const char *format, ...)
 {
        char    buf[256];
@@ -600,6 +605,7 @@ int dtrace_difo_validate_helper(dtrace_difo_t *dp)
                            subr == DIF_SUBR_INET_NTOA ||
                            subr == DIF_SUBR_INET_NTOA6 ||
                            subr == DIF_SUBR_INET_NTOP ||
+                           subr == DIF_SUBR_LINK_NTOP ||
                            subr == DIF_SUBR_LLTOSTR ||
                            subr == DIF_SUBR_RINDEX ||
                            subr == DIF_SUBR_STRCHR ||
@@ -3635,6 +3641,81 @@ next:
                break;
        }
 
+       case DIF_SUBR_LINK_NTOP: {
+               struct dtrace_hwtype_alen {
+                       int hwtype;
+                       size_t hwalen;
+               } hwinfo[] = {
+                       { ARPHRD_ETHER, ETH_ALEN },
+                       { ARPHRD_INFINIBAND, INFINIBAND_ALEN },
+                       { -1, 0 }
+               };
+/*
+ * Captures the maximum hardware address length among all the supported
+ * hardware types. Please update this macro when adding a new hardware type.
+ */
+#define DTRACE_MAX_HWTYPE_ALEN (ETH_ALEN > INFINIBAND_ALEN ? \
+                               ETH_ALEN : INFINIBAND_ALEN)
+               uint8_t hwaddr[DTRACE_MAX_HWTYPE_ALEN];
+               char *base;
+               size_t size, len;
+               int type, i;
+
+               type = (int)tupregs[0].dttk_value;
+               for (i = 0; hwinfo[i].hwtype != -1; i++) {
+                       if (type == hwinfo[i].hwtype)
+                               break;
+               }
+               if (hwinfo[i].hwtype == -1) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
+                       regs[rd] = 0;
+                       break;
+               }
+               len = hwinfo[i].hwalen;
+
+               /*
+                * Safely load the hardware address.
+                */
+               dtrace_bcopy((void *)(uintptr_t)tupregs[1].dttk_value, hwaddr,
+                            len);
+
+               /*
+                * Check if an hardware address string will fit in scratch.
+                * For every byte we need 3 characters (including ':').
+                */
+               size = len * 3;
+               if (!DTRACE_INSCRATCH(mstate, size)) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+                       regs[rd] = 0;
+                       break;
+               }
+               base = (char *)mstate->dtms_scratch_ptr;
+
+               /*
+                * Build the Hardware address string by working through the
+                * address from the beginning. Given a hardware address
+                * {0xa0, 0xaa, 0xff, 0xc, 0, 1, 2} of length 6, it will build
+                * a0:aa:ff:0c:00:01:02.
+                */
+               for (i = 0; i < len; i++) {
+                       if (hwaddr[i] < 16) {
+                               *base++ = '0';
+                               *base++ = dtrace_hexdigits[hwaddr[i]];
+                       } else {
+                               *base++ = dtrace_hexdigits[hwaddr[i] / 16];
+                               *base++ = dtrace_hexdigits[hwaddr[i] % 16];
+                       }
+
+                       if (i < len - 1)
+                               *base++ = ':';
+               }
+               *base++ = '\0';
+               regs[rd] = mstate->dtms_scratch_ptr;
+               mstate->dtms_scratch_ptr += size;
+#undef DTRACE_MAX_HWTYPE_ALEN
+               break;
+       }
+
        case DIF_SUBR_INET_NTOA:
        case DIF_SUBR_INET_NTOA6:
        case DIF_SUBR_INET_NTOP: {
@@ -3696,7 +3777,6 @@ next:
                        in6_addr_t      ip6;
                        int             firstzero, tryzero, numzero, v6end;
                        uint16_t        val;
-                       const char      digits[] = "0123456789abcdef";
 
                        /*
                         * Stringify using RFC 1884 convention 2 - 16 bit
@@ -3819,7 +3899,8 @@ next:
                                        *end-- = '0';
                                } else {
                                        for (; val; val /= 16) {
-                                               *end-- = digits[val % 16];
+                                               *end-- = \
+                                                   dtrace_hexdigits[val % 16];
                                        }
                                }
                        }
index 9e6e4db2f0ccf5e21c7d1c86ab8b3b1e8e277303..ea77988b788ef470262c16de25931c540b1daac9 100644 (file)
 #define DIF_SUBR_INET_NTOA             42
 #define DIF_SUBR_INET_NTOA6            43
 #define DIF_SUBR_D_PATH                        44
+#define DIF_SUBR_LINK_NTOP             45
 
-#define DIF_SUBR_MAX                   44
+#define DIF_SUBR_MAX                   45
 
 typedef uint32_t       dif_instr_t;