#ifndef CSUM_H #define CSUM_H #include #include #include #include #include "built_in.h" static inline unsigned short csum(unsigned short *buf, int nwords) { unsigned long sum; for (sum = 0; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum; } static inline uint16_t calc_csum(void *addr, size_t len) { return csum(addr, len >> 1); } static inline uint16_t csum_expected(uint16_t sum, uint16_t computed_sum) { uint32_t shouldbe; shouldbe = sum; shouldbe += ntohs(computed_sum); shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); return shouldbe; } /* Taken and modified from tcpdump, Copyright belongs to them! */ struct cksum_vec { const uint8_t *ptr; int len; }; #define ADDCARRY(x) \ do { if ((x) > 65535) \ (x) -= 65535; \ } while (0) #define REDUCE \ do { \ l_util.l = sum; \ sum = l_util.s[0] + l_util.s[1]; \ ADDCARRY(sum); \ } while (0) static inline uint16_t __in_cksum(const struct cksum_vec *vec, int veclen) { const uint16_t *w; int sum = 0, mlen = 0; int byte_swapped = 0; union { uint8_t c[2]; uint16_t s; } s_util; union { uint16_t s[2]; uint32_t l; } l_util; for (; veclen != 0; vec++, veclen--) { if (vec->len == 0) continue; w = (const uint16_t *) (const void *) vec->ptr; if (mlen == -1) { s_util.c[1] = *(const uint8_t *) w; sum += s_util.s; w = (const uint16_t *) (const void *) ((const uint8_t *) w + 1); mlen = vec->len - 1; } else mlen = vec->len; if ((1 & (unsigned long) w) && (mlen > 0)) { REDUCE; sum <<= 8; s_util.c[0] = *(const uint8_t *) w; w = (const uint16_t *) (const void *) ((const uint8_t *) w + 1); mlen--; byte_swapped = 1; } while ((mlen -= 32) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; w += 16; } mlen += 32; while ((mlen -= 8) >= 0) { sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; w += 4; } mlen += 8; if (mlen == 0 && byte_swapped == 0) continue; REDUCE; while ((mlen -= 2) >= 0) { sum += *w++; } if (byte_swapped) { REDUCE; sum <<= 8; byte_swapped = 0; if (mlen == -1) { s_util.c[1] = *(const uint8_t *) w; sum += s_util.s; mlen = 0; } else mlen = -1; } else if (mlen == -1) s_util.c[0] = *(const uint8_t *) w; } if (mlen == -1) { s_util.c[1] = 0; sum += s_util.s; } REDUCE; return (~sum & 0xffff); } static inline uint16_t p4_csum(const struct ip *ip, const uint8_t *data, uint16_t len, uint8_t next_proto) { struct cksum_vec vec[2]; struct pseudo_hdr { uint32_t src; uint32_t dst; uint8_t mbz; uint8_t proto; uint16_t len; } ph; ph.src = ip->ip_src.s_addr; ph.dst = ip->ip_dst.s_addr; ph.mbz = 0; ph.proto = next_proto; ph.len = htons(len); vec[0].ptr = (const uint8_t *) (void *) &ph; vec[0].len = sizeof(ph); vec[1].ptr = data; vec[1].len = len; return __in_cksum(vec, 2); } static inline uint16_t p6_csum(const struct ip6_hdr *ip6, const uint8_t *data, uint32_t len, uint8_t next_proto) { struct cksum_vec vec[2]; struct pseudo_hdr { uint8_t src[16]; uint8_t dst[16]; uint32_t len; uint8_t mbz[3]; uint8_t proto; } __packed ph; memcpy(&ph.src, ip6->ip6_src.s6_addr, sizeof(ph.src)); memcpy(&ph.dst, ip6->ip6_dst.s6_addr, sizeof(ph.dst)); ph.len = htons(len); memset(&ph.mbz, 0, sizeof(ph.mbz)); ph.proto = next_proto; vec[0].ptr = (const uint8_t *) (void *) &ph; vec[0].len = sizeof(ph); vec[1].ptr = data; vec[1].len = len; return __in_cksum(vec, 2); } #endif /* CSUM_H */ >space:mode:
authorSteven Rostedt <rostedt@goodmis.org>2016-07-28 22:30:43 -0400
committerSteven Rostedt <rostedt@goodmis.org>2016-08-02 12:57:48 -0400
commit377ccbb483738f84400ddf5840c7dd8825716985 (patch)
tree6e124d8704f768251cf65bc2b4c8e5dc5b11f679 /Makefile
parentb2e1c26f0b62531636509fbcb6dab65617ed8331 (diff)
Makefile: Mute warning for __builtin_return_address(>0) for tracing only
With the latest gcc compilers, they give a warning if __builtin_return_address() parameter is greater than 0. That is because if it is used by a function called by a top level function (or in the case of the kernel, by assembly), it can try to access stack frames outside the stack and crash the system. The tracing system uses __builtin_return_address() of up to 2! But it is well aware of the dangers that it may have, and has even added precautions to protect against it (see the thunk code in arch/x86/entry/thunk*.S) Linus originally added KBUILD_CFLAGS that would suppress the warning for the entire kernel, as simply adding KBUILD_CFLAGS to the tracing directory wouldn't work. The tracing directory plays a bit with the CFLAGS and requires a little more logic. This adds that special logic to only suppress the warning for the tracing directory. If it is used anywhere else outside of tracing, the warning will still be triggered. Link: http://lkml.kernel.org/r/20160728223043.51996267@grimm.local.home Tested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'Makefile')