From 5a80613abf2b6e0d50575fcacebb92f415ab2d0f Mon Sep 17 00:00:00 2001 From: "David J. Wilder" Date: Thu, 16 Jul 2009 16:47:01 -0700 Subject: This SNMP group of tapsets provides probes used to count SNMP management events. The probes mirror many of the SNMP statistics defined in /usr/include/linux/snmp.h. Each probe represents a single SNMP statistic or MIB. Each of the probe's handler is called when system performs an operation that would alter the associated statistic. Along with each probe is defined an indexed set of counters used to record probe hits. The probe handlers call a user supplied callback functions to determine which counter to alter. The user's callback should returns a key value that will be used to index the counter. For example a callback could return a unique value for each socket. This would results in a separate counter being used for each socket. tcpipstat.stp shows how snmp tapsets could be used. Tcpipstat collects and displays network statistics related to individual TCP sockets or groups of sockets. The statistics that are collected are simmer to that of the command netstat -s, only sorted and grouped by individual sockets. Signed-off-by: David Wilder --- tapset/ipmib.stp | 514 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tapset/linuxmib.stp | 102 +++++++++++ tapset/tcpmib.stp | 352 +++++++++++++++++++++++++++++++++++ 3 files changed, 968 insertions(+) create mode 100644 tapset/ipmib.stp create mode 100644 tapset/linuxmib.stp create mode 100644 tapset/tcpmib.stp (limited to 'tapset') diff --git a/tapset/ipmib.stp b/tapset/ipmib.stp new file mode 100644 index 00000000..3430a8a1 --- /dev/null +++ b/tapset/ipmib.stp @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2009 IBM Corp. + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + * + * Version 1.0 wilder@us.ibm.com 2009-07-06 + */ + +%{ /* pure */ +#include +#include +#include +#include +#include +%} + + +/* Commented globals represent statistics that are not supported in this + * version. + */ +global InReceives +// global InHdrErrors +// global InTooBigErrors +global InNoRoutes +global InAddrErrors +global InUnknownProtos +// global InTruncatedPkts +global InDiscards // included counts of InHdrErrors InTruncatedPkts +// global InDelivers +global ForwDatagrams +global OutRequests +// global OutDiscards +// global OutNoRoutes +global ReasmTimeout +global ReasmReqds +//global ReasmOKs +// global ReasmFails +global FragOKs +global FragFails +// global FragCreates +global InMcastPkts +global OutMcastPkts +global InBcastPkts +global OutBcastPkts + +/** + * sfunction ipmib_remote_addr - Get the remote ip address. + * + * Returns the remote ip address from an sk_buff. + * @skb: Pointer to a struct sk_buff. + * + */ +function ipmib_remote_addr:long (skb:long, SourceIsLocal:long) +{ + iphdr = __get_skb_iphdr(skb); + if ( SourceIsLocal ) + return ntohl(__ip_skb_daddr(iphdr)); + return ntohl(__ip_skb_saddr(iphdr)); +} + +/** + * sfunction ipmib_local_addr - Get the local ip address. + * + * Returns the local ip address from an sk_buff. + * @skb: Pointer to a struct sk_buff. + * + */ +function ipmib_local_addr:long (skb:long, SourceIsLocal:long) +{ + iphdr = __get_skb_iphdr(skb); + if ( SourceIsLocal ) + return ntohl(__ip_skb_saddr(iphdr)); + return ntohl(__ip_skb_daddr(iphdr)); +} + +/** + * sfunction ipmib_tcp_remote_port - Get the remote tcp port. + * + * Returns the remote tcp port from an sk_buff. + * @skb: Pointer to a struct sk_buff. + * + */ +function ipmib_tcp_remote_port:long (skb:long, SourceIsLocal:long) +{ + th = _plunge_into_tcphdr(skb); + if ( SourceIsLocal ) + return _tcphdr_get_dport(th); + return _tcphdr_get_sport(th); +} + +/** + * sfunction ipmib_tcp_local_port - Get the local tcp port. + * + * Returns the local tcp port from an sk_buff. + * @skb: Pointer to a struct sk_buff. + * + */ +function ipmib_tcp_local_port:long (skb:long, SourceIsLocal:long) +{ + th = _plunge_into_tcphdr(skb); + if ( SourceIsLocal ) + return _tcphdr_get_sport(th); + return _tcphdr_get_dport(th); +} + +/** + * sfunction ipmib_get_proto - Get the protocol value + * + * Returns the protocol value from ip header. + * @skb: Pointer to a struct sk_buff. + * + */ +function ipmib_get_proto:long (skb:long) +{ + iphdr = __get_skb_iphdr(skb); + return __ip_skb_proto(iphdr); +} + +/* Internal functions */ + +/* + * We can't assume the pointer to the sk_buff->transport_header + * has been updated, so we must calculate the value from the network_header. + * The caller must verify the skb is for a tcpip packet. + */ +function _plunge_into_tcphdr:long (skb:long) +%{ + struct sk_buff *skb = (struct sk_buff *)(long)THIS->skb; + /* as done by skb_network_header() */ + #ifdef NET_SKBUFF_DATA_USES_OFFSET + THIS->__retvalue=(long)kread(&(skb->network_header)) + + (long)(kread(&(skb->head))) + + (long)sizeof(struct tcphdr); + #else + THIS->__retvalue=(long)kread(&(skb->network_header)) + + (long)sizeof(struct tcphdr); + #endif + CATCH_DEREF_FAULT(); +%} + +function _tcphdr_get_sport:long (th:long) +%{ /* pure */ + struct tcphdr *th = (struct tcphdr *) (long) THIS->th; + THIS->__retvalue = ntohs(kread(&(th->source))); + CATCH_DEREF_FAULT(); +%} + +function _tcphdr_get_dport:long (th:long) +%{ /* pure */ + struct tcphdr *th = (struct tcphdr *) (long) THIS->th; + THIS->__retvalue = ntohs(kread(&(th->dest))); + CATCH_DEREF_FAULT(); +%} + +function _ehostunreach:long () +%{ + THIS->__retvalue = EHOSTUNREACH; +%} + +function _enetunreach:long () +%{ + THIS->__retvalue = ENETUNREACH; +%} + +function _icmp_dest_unreach:long () +%{ + THIS->__retvalue = ICMP_DEST_UNREACH; +%} + +function _icmp_prot_unreach:long () +%{ + THIS->__retvalue = ICMP_PROT_UNREACH; +%} + +function _net_rx_drop:long () +%{ + THIS->__retvalue = NET_RX_DROP; +%} + +function _icmp_time_exceeded:long () +%{ + THIS->__retvalue = ICMP_TIME_EXCEEDED; +%} + +function _icmp_exc_fragtime:long () +%{ + THIS->__retvalue = ICMP_EXC_FRAGTIME; +%} + +function _rtn_multicast:long () +%{ + THIS->__retvalue = RTN_MULTICAST; +%} + +function _rtn_broadcast:long () +%{ + THIS->__retvalue = RTN_BROADCAST; +%} + +/** + * probe tcpmib.InReceives - Count an arriving packet. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InReceives + * MIB: IPSTATS_MIB_INRECEIVES + * + */ +probe ipmib.InReceives=kernel.function("ip_rcv") +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InReceives[key] += op; +} + +/** + * probe tcpmib.InNoRoutes - Count an arriving packet with no matching socket. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InNoRoutes + * MIB: IPSTATS_MIB_INNOROUTES + * + */ +probe ipmib.InNoRoutes=kernel.function("ip_route_input").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + if ( $return != -_enetunreach()) next; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InNoRoutes[key] += op; +} + +/** + * probe tcpmib.InAddrErrors - Count arriving packets with an incorrect address. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InAddrErrors + * MIB: IPSTATS_MIB_INADDRERRORS + * + */ +probe ipmib.InAddrErrors=kernel.function("ip_route_input").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + if ( $return != -_ehostunreach()) next; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InAddrErrors[key] += op; +} + +/** + * probe tcpmib.InUnknownProtos - Count arriving packets with an unbound proto. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InUnknownProtos + * MIB: IPSTATS_MIB_INUNKNOWNPROTOS + * + */ + +/* icmp_send() is called by ip_local_deliver_finish() */ +probe ipmib.InUnknownProtos=kernel.function("icmp_send") +{ + skb = $skb_in; + op = 1; + SourceIsLocal = 0; + if (($type==_icmp_dest_unreach())&&($code==_icmp_prot_unreach())){ + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InUnknownProtos[key] += op; + } +} + +/** + * probe tcpmib.InDiscards - Count discarded inbound packets. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InDiscards + * MIB: STATS_MIB_INDISCARDS + * + */ + +/* + This stat combines all instances of IPSTATS_MIB_INHDRERRORS, + IPSTATS_MIB_INTRUNCATEDPKTS, and STATS_MIB_INDISCARDS. +*/ +probe ipmib.InDiscards=kernel.function("ip_rcv").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + if ( $return != _net_rx_drop() ) next; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InDiscards[key] += op; +} + +/** + * probe tcpmib.ForwDatagrams + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ForwDatagrams + * MIB: IPSTATS_MIB_OUTFORWDATAGRAMS + * + */ +probe ipmib.ForwDatagrams=kernel.function("ip_forward_finish"), + kernel.function("ipmr_forward_finish") +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) ForwDatagrams[key] += op; +} + +/** + * probe tcpmib.OutRequests - Count a request to send a packet. + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: OutRequests + * MIB: IPSTATS_MIB_OUTREQUESTS + * + */ +probe ipmib.OutRequests=kernel.function("ip_output"), + kernel.function("ip_mc_output") +{ + skb = $skb; + op = 1; + SourceIsLocal = 1; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) OutRequests[key] += op; +} + +/** + * probe tcpmib.ReasmTimeout + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ReasmTimeout + * MIB: IPSTATS_MIB_REASMTIMEOUT + * + */ +probe ipmib.ReasmTimeout=kernel.function("icmp_send") +{ + skb = $skb_in; + op = 0; + SourceIsLocal = 1; + if(($type==_icmp_time_exceeded())&&($code==_icmp_exc_fragtime())){ + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) ReasmTimeout[key] += op; + } +} + +/** + * probe tcpmib.ReasmReqds + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ReasmReqds + * MIB: IPSTATS_MIB_REASMREQDS + * + */ +probe ipmib.ReasmReqds=kernel.function("ip_defrag") +{ + skb = $skb; + op = 0; + SourceIsLocal = 1; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) ReasmReqds[key] += op; +} + +/** + * probe tcpmib.FragOKs + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: FragOKs + * MIB: IPSTATS_MIB_FRAGOKS + * + */ +probe ipmib.FragOKs=kernel.function("ip_fragment").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 1; + if ( $return ) next + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) FragOKs [key] += op; +} + +/** + * probe tcpmib.FragFails + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: FragFails + * MIB: IPSTATS_MIB_FRAGFAILS + * + */ +probe ipmib.FragFails=kernel.function("ip_fragment").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 1; + if (!$return ) next + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) FragFails [key] += op; +} + +function _input_route_type:long (skb:long) +%{ /* pure */ + struct rtable *rt; + struct sk_buff *skb = (struct sk_buff *)(long)THIS->skb; + rt = (struct rtable *)kread(&(skb->rtable)); + THIS->__retvalue = kread(&(rt->rt_type)); + CATCH_DEREF_FAULT(); +%} + +function _output_route_type:long (skb:long) +%{ /* pure */ + struct rtable *rt; + struct dst_entry *dst; + struct sk_buff *skb = (struct sk_buff *)(long)THIS->skb; + dst = (struct dst_entry *)kread(&(skb->dst)); + rt = (struct rtable *)dst; + THIS->__retvalue = kread(&(rt->rt_type)); + CATCH_DEREF_FAULT(); +%} + +/** + * probe tcpmib.InMcastPkts + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InMcastPkts + * MIB: IPSTATS_MIB_INMCASTPKTS + * + */ +probe ipmib.InMcastPkts=kernel.function("ip_rcv_finish").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + if ($return == _net_rx_drop()) next; + if (_input_route_type(skb) != _rtn_multicast()) next; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InMcastPkts[key] += op; +} + +/** + * probe tcpmib.OutMcastPkts + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: OutMcastPkts + * MIB: IPSTATS_MIB_OUTMCASTPKTS + * + */ +probe ipmib.OutMcastPkts=kernel.function("ip_finish_output2") +{ + skb = $skb; + op = 1; + SourceIsLocal = 1; + if (_output_route_type(skb) != _rtn_multicast()) next + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) OutMcastPkts[key] += op; +} + +/** + * probe tcpmib.InBcastPkts + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InBcastPkts + * MIB: IPSTATS_MIB_INBCASTPKTS + * + */ +probe ipmib.InBcastPkts=kernel.function("ip_rcv_finish").return +{ + skb = $skb; + op = 1; + SourceIsLocal = 0; + if ($return == _net_rx_drop()) next; + if (_input_route_type(skb) != _rtn_broadcast()) next; + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) InBcastPkts[key] += op; +} + +/** + * probe tcpmib.OutBcastPkts + * @skb: Pointer to the struct sk_buff being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: OutBcastPkts + * MIB: IPSTATS_MIB_OUTBCASTPKTS + * + */ +probe ipmib.OutBcastPkts=kernel.function("ip_finish_output2") +{ + skb = $skb; + op = 1; + SourceIsLocal = 1; + if (_output_route_type(skb) != _rtn_broadcast()) next + key = ipmib_filter_key(skb,op,SourceIsLocal); + if ( key ) OutBcastPkts[key] += op; +} diff --git a/tapset/linuxmib.stp b/tapset/linuxmib.stp new file mode 100644 index 00000000..e19755a9 --- /dev/null +++ b/tapset/linuxmib.stp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2009 IBM Corp. + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + * + * Version 1.0 wilder@us.ibm.com 2009-07-06 + */ + +global DelayedACKs /* LINUX_MIB_DELAYEDACKS */ +global ListenOverflows /* LINUX_MIB_LISTENOVERFLOWS */ +global ListenDrops /* LINUX_MIB_LISTENDROPS */ +global TCPMemoryPressures /* LINUX_MIB_TCPMEMORYPRESSURES */ + +/** + * probe tcpmib.DelayedACKs - Count of delayed acks. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: DelayedACKs + * MIB: LINUX_MIB_DELAYEDACKS + * + */ +global indelack_timer +probe linuxmib.DelayedACKs = _linuxmib.DelayedACKs.* {} + +probe _linuxmib.DelayedACKs.A = kernel.function("tcp_send_ack") +{ + sk=$sk + if ( !indelack_timer[sk] ) next + op=1 + key = linuxmib_filter_key(sk,op); + if ( key ) DelayedACKs[key] += op; +} + +probe _linuxmib.DelayedACKs.B = kernel.function("tcp_delack_timer") +{ + sk=$data + indelack_timer[sk]=1 +} + +probe _linuxmib.DelayedACKs.C = kernel.function("tcp_delack_timer").return +{ + sk=$data + indelack_timer[sk]=0; +} + +/** + * probe tcpmib.ListenOverflows - Count of times a listen queue overflowed + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ListenOverflows + * MIB: LINUX_MIB_LISTENOVERFLOWS + * + */ +probe linuxmib.ListenOverflows=kernel.function("tcp_v4_syn_recv_sock").return +{ + sk = $sk + if ( $return ) next + if ( $sk->sk_ack_backlog <= $sk->sk_max_ack_backlog ) next + op = 1; + key = linuxmib_filter_key(sk,op); + if ( key ) ListenOverflows[key] += op; +} + +/** + * probe tcpmib.ListenDrops - Count of times conn request that were dropped. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ListenDrops + * MIB: LINUX_MIB_LISTENDROPS + * + */ +probe linuxmib.ListenDrops=kernel.function("tcp_v4_syn_recv_sock").return +{ + sk = $sk + if ( $return ) next + op = 1; + key = linuxmib_filter_key(sk,op); + if ( key ) ListenDrops[key] += op; +} + +/** + * probe tcpmib.TCPMemoryPressures - Count of times memory pressure was used. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: TCPMemoryPressures + * MIB: LINUX_MIB_TCPMEMORYPRESSURES + * + */ +probe linuxmib.TCPMemoryPressures=kernel.function("tcp_enter_memory_pressure") +{ + sk = $sk + op = 1; + if ( $tcp_memory_pressure ) next + key = linuxmib_filter_key(sk,op); + if ( key ) TCPMemoryPressures[key] += op; +} diff --git a/tapset/tcpmib.stp b/tapset/tcpmib.stp new file mode 100644 index 00000000..e3e76900 --- /dev/null +++ b/tapset/tcpmib.stp @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2009 IBM Corp. + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + * + * Version 1.0 wilder@us.ibm.com 2009-07-06 + */ + +/* Global counter definitions for mib TCP_MIB. */ + +%{ +#include +#include +#include +#include +#include +%} + +global ActiveOpens +global AttemptFails +global CurrEstab +global EstabResets +// global InErrs, this mib is not yet supported +global InSegs +global OutRsts +global OutSegs +global PassiveOpens +global RetransSegs + +/** + * sfunction tcpmib_get_state - Get a socket's state. + * + * Returns the sk_state from a struct sock. + * @sk: Pointer to a struct sock. + * + */ +function tcpmib_get_state:long (sk:long) +%{ /* pure */ + struct sock *sk = (struct sock *)(long)THIS->sk; + THIS->__retvalue = kread(&(sk->sk_state)); + CATCH_DEREF_FAULT(); +%} + +/** + * sfunction tcpmib_local_addr - Get the source address. + * + * Returns the saddr from a struct inet_sock. + * @sk: Pointer to a struct inet_sock. + * + */ +function tcpmib_local_addr:long(sk:long) +%{ /* pure */ + struct inet_sock *inet = (struct inet_sock *) (long) THIS->sk; + THIS->__retvalue = ntohl(kread(&(inet->saddr))); + CATCH_DEREF_FAULT(); +%} + +/** + * sfunction tcpmib_remote_addr - Get the remote address. + * + * Returns the daddr from a struct inet_sock. + * @sk: Pointer to a struct inet_sock. + * + */ +function tcpmib_remote_addr:long(sk:long) +%{ /* pure */ + struct inet_sock *inet = (struct inet_sock *) (long) THIS->sk; + THIS->__retvalue = ntohl(kread(&(inet->daddr))); + CATCH_DEREF_FAULT(); +%} + +/** + * sfunction tcpmib_local_port - Get the local port. + * + * Returns the sport from a struct inet_sock. + * @sk: Pointer to a struct inet_sock. + * + */ +function tcpmib_local_port:long(sk:long) +%{ /* pure */ + struct inet_sock *inet = (struct inet_sock *) (long) THIS->sk; + THIS->__retvalue = ntohs(kread(&(inet->sport))); + CATCH_DEREF_FAULT(); +%} + +/** + * sfunction tcpmib_remote_port - Get the remote port. + * + * Returns the dport from a struct inet_sock. + * @sk: Pointer to a struct inet_sock. + * + */ +function tcpmib_remote_port:long(sk:long) +%{ /* pure */ + struct inet_sock *inet = (struct inet_sock *) (long) THIS->sk; + THIS->__retvalue = ntohs(kread(&(inet->dport))); + CATCH_DEREF_FAULT(); +%} + +/** + * probe tcpmib.ActiveOpens - Count an active opening of a socket. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: ActiveOpens + * MIB: TCP_MIB_ACTIVEOPENS + * + */ +probe +tcpmib.ActiveOpens=kernel.function("tcp_connect").return +{ + sk = $sk; + op = 1; + if ( $return ) next; + key = tcpmib_filter_key(sk,op); + if ( key ) ActiveOpens[key] += op; +} + +/** + * probe tcpmib.AttemptFails - Count a failed attempt to open a socket. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: AttemptFails + * MIB: TCP_MIB_ATTEMPTFAILS + * + */ +probe +tcpmib.AttemptFails=kernel.function("tcp_done") +{ + sk = $sk; + state = tcpmib_get_state(sk); + op = 1; + + TCP_SYN_SENT = 2; + TCP_SYN_RECV = 3; + if( state == TCP_SYN_SENT || state == TCP_SYN_RECV){ + key = tcpmib_filter_key(sk,op); + if ( key ) AttemptFails[key] += op; + } +} + +/** + * probe tcpmib.CurrEstab - Update the count of open sockets. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: CurrEstab + * MIB: TCP_MIB_CURRESTAB + * + */ +probe +tcpmib.CurrEstab=kernel.function("tcp_set_state") +{ + sk = $sk; + state = $state; + oldstate = tcpmib_get_state(sk); + + TCP_ESTABLISHED = 1; + if ( oldstate == TCP_ESTABLISHED ) { + op = -1; + key = tcpmib_filter_key(sk,op); + if ( key ) CurrEstab[key] += op; + } else { + if ( state == TCP_ESTABLISHED ) { + op = 1; + key = tcpmib_filter_key(sk,op); + if ( key ) CurrEstab[key] += op; + } + } +} + +/** + * probe tcpmib.EstabResets - Count the reset of a socket. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: EstabResets + * MIB: TCP_MIB_ESTABRESETS + * + */ +probe +tcpmib.EstabResets=kernel.function("tcp_set_state") +{ + sk = $sk; + state = $state; + oldstate = tcpmib_get_state(sk); + op = 1; + + TCP_CLOSE = 7; + TCP_CLOSE_WAIT = 8; + TCP_ESTABLISHED = 1; + if ( ( state == TCP_CLOSE ) && + (oldstate == TCP_CLOSE_WAIT || oldstate == TCP_ESTABLISHED) ){ + key = tcpmib_filter_key(sk,op); + if ( key ) EstabResets[key] += op; + } +} + +/** + * probe tcpmib.InSegs - Count an incomming tcp segment. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: InSegs + * MIB: TCP_MIB_INSEGS + * + */ +probe +tcpmib.InSegs=kernel.function("__inet_lookup_established").return +{ + sk=$return + op=1 + key = tcpmib_filter_key(sk,op); + if ( key ) InSegs[key] += op; +} + +/** + * probe tcpmib.OutRsts - Count the sending of a reset packet. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: OutRsts + * MIB: TCP_MIB_OUTRSTS + * + */ +probe +tcpmib.OutRsts = tcpmib.OutRsts.A, + tcpmib.OutRsts.B { } + +function _rtn_local:long () +%{ + THIS->__retvalue = RTN_LOCAL; +%} + +function _is_reset:long (skb:long) +%{ /* pure */ + struct tcphdr *th; + struct sk_buff *skb = (struct sk_buff *)(long)THIS->skb; + + #ifdef NET_SKBUFF_DATA_USES_OFFSET + th = (struct tcphdr *)(kread(&(skb->network_header)) + kread(&(skb->head))); + #else + th = (struct tcphdr *)kread(&(skb->network_header)); + #endif + THIS->__retvalue = th->rst; + CATCH_DEREF_FAULT(); +%} + +function _tcpmib_input_route_type:long (skb:long) +%{ /* pure */ + struct rtable *rt; + struct sk_buff *skb = (struct sk_buff *)(long)THIS->skb; + rt = (struct rtable *)kread(&(skb->rtable)); + THIS->__retvalue = kread(&(rt->rt_type)); + CATCH_DEREF_FAULT(); +%} + +/* + * note: + * tcp_v4_send_reset may be called with a NULL sk. + * This happens when sending a reset in response to a syn + * when no socket exists (for example the service is not running). + * Without a socket we can't count the reset. + */ +probe +tcpmib.OutRsts.A=kernel.function("tcp_v4_send_reset") +{ + sk = $sk; + skb = $skb + op = 1; + if ( _is_reset(skb) ) next + if (_tcpmib_input_route_type($skb) != _rtn_local() ) + next; + key = tcpmib_filter_key(sk,op); + if ( key ) OutRsts[key] += op; +} + +probe +tcpmib.OutRsts.B= kernel.function("tcp_send_active_reset") +{ + /* Almost correct, + * If alloc_skb() fails it incorrectly bumps TCP_MIB_OUTRSTS, + */ + sk = $sk; + op = 1; + key = tcpmib_filter_key(sk,op); + if ( key ) OutRsts[key] += op; +} + +/** + * probe tcpmib.OutSegs - Count the sending of a TCP segment. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: OutSegs + * MIB: TCP_MIB_OUTSEGS + * + */ +probe +tcpmib.OutSegs=kernel.function("ip_queue_xmit").return +{ + if ( $return < 0 ) next; + sk = $skb->sk; + op = 1; + + // Only count the events with protocol IPPROTO_TCP,6. + iphdr = __get_skb_iphdr($skb); + if( !(__ip_skb_proto(iphdr) == 6) ) next ; + key = tcpmib_filter_key(sk,op); + if ( key ) OutSegs[key] += op; +} + +/** + * probe tcpmib.PassiveOpens - Count the passive creation of a socket. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: PassiveOpens + * MIB: TCP_MIB_PASSIVEOPENS + * + */ +probe +tcpmib.PassiveOpens=kernel.function("tcp_v4_syn_recv_sock").return +{ + sk = $return; + op = 1; + if ( !sk ) next; + key = tcpmib_filter_key(sk,op); + if ( key ) PassiveOpens[key] += op; +} + +/** + * probe tcpmib.RetransSegs - Count the retransmission of a TCP segment. + * @sk: Pointer to the struct sock being acted on. + * @op: Value to be added to the counter (Operation). + * + * Counter Name: RetransSegs + * MIB: TCP_MIB_RETRANSSEGS + * + */ +probe +tcpmib.RetransSegs=kernel.function("tcp_retransmit_skb").return +{ + sk = $sk; + op = 1; + if ( $return ) next; + key = tcpmib_filter_key(sk,op); + if ( key ) RetransSegs[key] += op; +} -- cgit