工具小用法 dropwatch ss perf

dropwatch的内核把kfree_skb分成二类:

  • 人畜无害的调用consume_skb
  •  需要丢包的调用kfree_skb

perf record -g -a -e skb:kfree_skb  跟踪kfree_skb 就可以知道 丢包!!

 

 

 

内核通过kfree_skb释放skb,kfree_skb函数中已经埋下了trace点,并且通过__builtin_return_address(0)记录下了调用kfree_skb的函数地址并传给location参数:

 

/**
 *      kfree_skb - free an sk_buff
 *      @skb: buffer to free
 *
 *      Drop a reference to the buffer and free it if the usage count has
 *      hit zero.
 */
void kfree_skb(struct sk_buff *skb)
{
        if (unlikely(!skb))
                return;
        if (likely(atomic_read(&skb->users) == 1))
                smp_rmb();
        else if (likely(!atomic_dec_and_test(&skb->users)))
                return;
        trace_kfree_skb(skb, __builtin_return_address(0));
        __kfree_skb(skb);
}
EXPORT_SYMBOL(kfree_skb);


/*
 * Tracepoint for free an sk_buff:
 */
TRACE_EVENT(kfree_skb,

        TP_PROTO(struct sk_buff *skb, void *location),

        TP_ARGS(skb, location),

        TP_STRUCT__entry(
                __field(        void *,         skbaddr         )
                __field(        void *,         location        )
                __field(        unsigned short, protocol        )
        ),

        TP_fast_assign(
                __entry->skbaddr = skb;
                __entry->location = location;
                __entry->protocol = ntohs(skb->protocol);
        ),

        TP_printk("skbaddr=%p protocol=%u location=%p",
                __entry->skbaddr, __entry->protocol, __entry->location)
);

 

看下 ststap 中的dropwatch代码

1 #! /usr/bin/env stap
  2 
  3 ############################################################
  4 # Dropwatch.stp
  5 # Author: Neil Horman <nhorman@redhat.com>
  6 # An example script to mimic the behavior of the dropwatch utility
  7 # http://fedorahosted.org/dropwatch
  8 ############################################################
  9 
 10 # Array to hold the list of drop points we find
 11 global locations
 12 
 13 # Note when we turn the monitor on and off
 14 probe begin { printf("Monitoring for dropped packets\n") }
 15 probe end { printf("Stopping dropped packet monitor\n") }
 16 
 17 # increment a drop counter for every location we drop at
 18 probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }
 19 
 20 # Every 5 seconds report our drop locations
 21 probe timer.sec(5)
 22 {
 23   printf("\n")
 24   foreach (l in locations-) {
 25     printf("%d packets dropped at %s\n",
 26            @count(locations[l]), symname(l))
 27   }
 28   delete locations
 29 }
~                                         

 kfree_skb 中的__builtin_return_address表示什么意思?

  • __builtin_return_address(0)的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕后,返回,所谓返回地址就是那时候的地址。
  • __builtin_return_address(1)的含义是,得到当前函数的调用者的返回地址。注意是调用者的返回地址,而不是函数起始地址
Getting the Return or Frame Address of a Function

These functions may be used to get information about the callers of a function.

Built-in Function: void * __builtin_return_address (unsigned int level)

This function returns the return address of the current function, or of one of its callers. The level argument is number of frames to scan up the call stack. A value of 0 yields the return address of the current function, a value of 1 yields the return address of the caller of the current function, and so forth. When inlining the expected behavior is that the function returns the address of the function that is returned to. To work around this behavior use the noinline function attribute.

The level argument must be a constant integer.

On some machines it may be impossible to determine the return address of any function other than the current one; in such cases, or when the top of the stack has been reached, this function returns an unspecified value. In addition, __builtin_frame_address may be used to determine if the top of the stack has been reached.

Additional post-processing of the returned value may be needed, see __builtin_extract_return_addr.

The stored representation of the return address in memory may be different from the address returned by __builtin_return_address. For example, on AArch64 the stored address may be mangled with return address signing whereas the address returned by __builtin_return_address is not.

Calling this function with a nonzero argument can have unpredictable effects, including crashing the calling program. As a result, calls that are considered unsafe are diagnosed when the -Wframe-address option is in effect. Such calls should only be made in debugging situations.

On targets where code addresses are representable as void *,

void *addr = __builtin_extract_return_addr (__builtin_return_address (0));
gives the code address where the current function would return. For example, such an address may be used with dladdr or other interfaces that work with code addresses.

Built-in Function: void * __builtin_extract_return_addr (void *addr)

The address as returned by __builtin_return_address may have to be fed through this function to get the actual encoded address. For example, on the 31-bit S/390 platform the highest bit has to be masked out, or on SPARC platforms an offset has to be added for the true next instruction to be executed.

If no fixup is needed, this function simply passes through addr.

Built-in Function: void * __builtin_frob_return_addr (void *addr)

This function does the reverse of __builtin_extract_return_addr.

Built-in Function: void * __builtin_frame_address (unsigned int level)

This function is similar to __builtin_return_address, but it returns the address of the function frame rather than the return address of the function. Calling __builtin_frame_address with a value of 0 yields the frame address of the current function, a value of 1 yields the frame address of the caller of the current function, and so forth.

The frame is the area on the stack that holds local variables and saved registers. The frame address is normally the address of the first word pushed on to the stack by the function. However, the exact definition depends upon the processor and the calling convention. If the processor has a dedicated frame pointer register, and the function has a frame, then __builtin_frame_address returns the value of the frame pointer register.

On some machines it may be impossible to determine the frame address of any function other than the current one; in such cases, or when the top of the stack has been reached, this function returns 0 if the first frame pointer is properly initialized by the startup code.

Calling this function with a nonzero argument can have unpredictable effects, including crashing the calling program. As a result, calls that are considered unsafe are diagnosed when the -Wframe-address option is in effect. Such calls should only be made in debugging situations.
View Code

 

linux ss 命令用法

ss可以通过 dst/src/dport/sprot 语法来过滤连接的来源和目标,来源端口和目标端口

使用方法如下:

匹配远程地址和端口号

ss dst 192.168.119.113:443

匹配本地地址和端口号

ss src 192.168.119.103:80

将本地或者远程端口和一个数比较

可以使用下面的语法做端口号的过滤:

ss dport OP PORT$ ss sport OP PORT

OP 可以代表以下任意一个:

| <= | le | 小于或等于某个端口号 |
| >= | ge | 大于或等于某个端口号 |
| == | eq | 等于某个端口号 |
| != | ne | 不等于某个端口号 |
| > | gt | 大于某个端口号 |
| < | lt | 小于某个端口号 |

ss -tunl sport \< 50//注意,需要对尖括号使用转义符
ss -tunl sport lt 50

 

 

posted @ 2021-05-12 11:04  codestacklinuxer  阅读(427)  评论(0编辑  收藏  举报