From bc7666bf8cf51f174593f12cf21ef6e3026afa2a Mon Sep 17 00:00:00 2001 From: Girish Moodalbail Date: Mon, 10 Apr 2017 17:39:14 -0700 Subject: [PATCH] dtrace: implement link_ntop() DTrace subroutine logic 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 Reviewed-by: Nick Alcock [nca: reworded commit message a bit] Orabug: 25931479 --- dtrace/.gitignore | 12 +++ dtrace/dtrace_dif.c | 85 ++++++++++++++++++- .../include/uapi/linux/dtrace/dif_defines.h | 3 +- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/dtrace/.gitignore b/dtrace/.gitignore index 008c2d4a7b16..d9e47cc0d9ec 100644 --- a/dtrace/.gitignore +++ b/dtrace/.gitignore @@ -25,3 +25,15 @@ Module.symvers # *.sdtinfo.c *.sdtstub.S + +# +# cscope files +# +cscope.* +ncscope.* + +# +# Top-level tag files +# +/tags +/*TAGS diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index b31ec8e097f0..0906c7904fde 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -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]; } } } diff --git a/dtrace/include/uapi/linux/dtrace/dif_defines.h b/dtrace/include/uapi/linux/dtrace/dif_defines.h index 9e6e4db2f0cc..ea77988b788e 100644 --- a/dtrace/include/uapi/linux/dtrace/dif_defines.h +++ b/dtrace/include/uapi/linux/dtrace/dif_defines.h @@ -226,8 +226,9 @@ #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; -- 2.50.1