Annotation of embedaddon/bmon/src/in_netlink.c, revision 1.1.1.3

1.1       misho       1: /*
1.1.1.2   misho       2:  * in_netlink.c            Netlink input
1.1       misho       3:  *
1.1.1.2   misho       4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
                      5:  * Copyright (c) 2013 Red Hat, Inc.
1.1       misho       6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a
                      8:  * copy of this software and associated documentation files (the "Software"),
                      9:  * to deal in the Software without restriction, including without limitation
                     10:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
                     11:  * and/or sell copies of the Software, and to permit persons to whom the
                     12:  * Software is furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included
                     15:  * in all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
                     18:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
                     22:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
                     23:  * DEALINGS IN THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include <bmon/bmon.h>
                     27: #include <bmon/input.h>
1.1.1.2   misho      28: #include <bmon/element.h>
                     29: #include <bmon/attr.h>
1.1       misho      30: #include <bmon/conf.h>
1.1.1.2   misho      31: #include <bmon/input.h>
1.1       misho      32: #include <bmon/utils.h>
                     33: 
1.1.1.2   misho      34: #ifndef SYS_BSD
1.1       misho      35: 
                     36: static int c_notc = 0;
1.1.1.2   misho      37: static struct element_group *grp;
                     38: static struct bmon_module netlink_ops;
1.1       misho      39: 
1.1.1.3 ! misho      40: #include <linux/if.h>
        !            41: 
1.1       misho      42: #include <netlink/netlink.h>
                     43: #include <netlink/cache.h>
1.1.1.2   misho      44: #include <netlink/utils.h>
1.1       misho      45: #include <netlink/route/link.h>
1.1.1.2   misho      46: #include <netlink/route/tc.h>
1.1       misho      47: #include <netlink/route/qdisc.h>
                     48: #include <netlink/route/class.h>
1.1.1.2   misho      49: #include <netlink/route/classifier.h>
                     50: #include <netlink/route/qdisc/htb.h>
1.1       misho      51: 
1.1.1.3 ! misho      52: /* These counters are not available prior to libnl 3.2.25. Set them to -1 so
        !            53:  * rtnl_link_get_stat() won't be called for them. */
        !            54: #if LIBNL_CURRENT < 220
        !            55: # define RTNL_LINK_ICMP6_CSUMERRORS    -1
        !            56: # define RTNL_LINK_IP6_CSUMERRORS      -1
        !            57: # define RTNL_LINK_IP6_NOECTPKTS       -1
        !            58: # define RTNL_LINK_IP6_ECT1PKTS                -1
        !            59: # define RTNL_LINK_IP6_ECT0PKTS                -1
        !            60: # define RTNL_LINK_IP6_CEPKTS          -1
        !            61: #endif
        !            62: 
        !            63: /* Not available prior to libnl 3.2.29 */
        !            64: #if LIBNL_CURRENT < 224
        !            65: # define RTNL_LINK_RX_NOHANDLER                -1
        !            66: #endif
        !            67: 
1.1.1.2   misho      68: static struct attr_map link_attrs[] = {
                     69: {
                     70:        .name           = "bytes",
                     71:        .type           = ATTR_TYPE_COUNTER,
                     72:        .unit           = UNIT_BYTE,
                     73:        .description    = "Bytes",
                     74:        .rxid           = RTNL_LINK_RX_BYTES,
                     75:        .txid           = RTNL_LINK_TX_BYTES,
                     76: },
                     77: {
                     78:        .name           = "packets",
                     79:        .type           = ATTR_TYPE_COUNTER,
                     80:        .unit           = UNIT_NUMBER,
                     81:        .description    = "Packets",
                     82:        .rxid           = RTNL_LINK_RX_PACKETS,
                     83:        .txid           = RTNL_LINK_TX_PACKETS,
                     84: },
                     85: {
                     86:        .name           = "errors",
                     87:        .type           = ATTR_TYPE_COUNTER,
                     88:        .unit           = UNIT_NUMBER,
                     89:        .description    = "Errors",
                     90:        .rxid           = RTNL_LINK_RX_ERRORS,
                     91:        .txid           = RTNL_LINK_TX_ERRORS,
                     92: },
                     93: {
                     94:        .name           = "drop",
                     95:        .type           = ATTR_TYPE_COUNTER,
                     96:        .unit           = UNIT_NUMBER,
                     97:        .description    = "Dropped",
                     98:        .rxid           = RTNL_LINK_RX_DROPPED,
                     99:        .txid           = RTNL_LINK_TX_DROPPED,
                    100: },
                    101: {
                    102:        .name           = "compressed",
                    103:        .type           = ATTR_TYPE_COUNTER,
                    104:        .unit           = UNIT_NUMBER,
                    105:        .description    = "Compressed",
                    106:        .rxid           = RTNL_LINK_RX_COMPRESSED,
                    107:        .txid           = RTNL_LINK_TX_COMPRESSED,
                    108: },
                    109: {
1.1.1.3 ! misho     110:        .name           = "nohandler",
        !           111:        .type           = ATTR_TYPE_COUNTER,
        !           112:        .unit           = UNIT_NUMBER,
        !           113:        .description    = "No Handler",
        !           114:        .rxid           = RTNL_LINK_RX_NOHANDLER,
        !           115:        .txid           = -1,
        !           116: },
        !           117: {
1.1.1.2   misho     118:        .name           = "fifoerr",
                    119:        .type           = ATTR_TYPE_COUNTER,
                    120:        .unit           = UNIT_NUMBER,
                    121:        .description    = "FIFO Error",
                    122:        .rxid           = RTNL_LINK_RX_FIFO_ERR,
                    123:        .txid           = RTNL_LINK_TX_FIFO_ERR,
                    124: },
                    125: {
                    126:        .name           = "lenerr",
                    127:        .type           = ATTR_TYPE_COUNTER,
                    128:        .unit           = UNIT_NUMBER,
                    129:        .description    = "Length Error",
                    130:        .rxid           = RTNL_LINK_RX_LEN_ERR,
                    131:        .txid           = -1,
                    132: },
                    133: {
                    134:        .name           = "overerr",
                    135:        .type           = ATTR_TYPE_COUNTER,
                    136:        .unit           = UNIT_NUMBER,
                    137:        .description    = "Over Error",
                    138:        .rxid           = RTNL_LINK_RX_OVER_ERR,
                    139:        .txid           = -1,
                    140: },
                    141: {
                    142:        .name           = "crcerr",
                    143:        .type           = ATTR_TYPE_COUNTER,
                    144:        .unit           = UNIT_NUMBER,
                    145:        .description    = "CRC Error",
                    146:        .rxid           = RTNL_LINK_RX_CRC_ERR,
                    147:        .txid           = -1,
                    148: },
                    149: {
                    150:        .name           = "frameerr",
                    151:        .type           = ATTR_TYPE_COUNTER,
                    152:        .unit           = UNIT_NUMBER,
                    153:        .description    = "Frame Error",
                    154:        .rxid           = RTNL_LINK_RX_FRAME_ERR,
                    155:        .txid           = -1,
                    156: },
                    157: {
                    158:        .name           = "misserr",
                    159:        .type           = ATTR_TYPE_COUNTER,
                    160:        .unit           = UNIT_NUMBER,
                    161:        .description    = "Missed Error",
                    162:        .rxid           = RTNL_LINK_RX_MISSED_ERR,
                    163:        .txid           = -1,
                    164: },
                    165: {
                    166:        .name           = "aborterr",
                    167:        .type           = ATTR_TYPE_COUNTER,
                    168:        .unit           = UNIT_NUMBER,
                    169:        .description    = "Abort Error",
                    170:        .rxid           = -1,
                    171:        .txid           = RTNL_LINK_TX_ABORT_ERR,
                    172: },
                    173: {
                    174:        .name           = "carrerr",
                    175:        .type           = ATTR_TYPE_COUNTER,
                    176:        .unit           = UNIT_NUMBER,
                    177:        .description    = "Carrier Error",
                    178:        .rxid           = -1,
                    179:        .txid           = RTNL_LINK_TX_CARRIER_ERR,
                    180: },
                    181: {
                    182:        .name           = "hbeaterr",
                    183:        .type           = ATTR_TYPE_COUNTER,
                    184:        .unit           = UNIT_NUMBER,
                    185:        .description    = "Heartbeat Error",
                    186:        .rxid           = -1,
                    187:        .txid           = RTNL_LINK_TX_HBEAT_ERR,
                    188: },
                    189: {
                    190:        .name           = "winerr",
                    191:        .type           = ATTR_TYPE_COUNTER,
                    192:        .unit           = UNIT_NUMBER,
                    193:        .description    = "Window Error",
                    194:        .rxid           = -1,
                    195:        .txid           = RTNL_LINK_TX_WIN_ERR,
                    196: },
                    197: {
                    198:        .name           = "coll",
                    199:        .type           = ATTR_TYPE_COUNTER,
                    200:        .unit           = UNIT_NUMBER,
                    201:        .description    = "Collisions",
                    202:        .rxid           = -1,
                    203:        .txid           = RTNL_LINK_COLLISIONS,
                    204: },
                    205: {
                    206:        .name           = "mcast",
                    207:        .type           = ATTR_TYPE_COUNTER,
                    208:        .unit           = UNIT_NUMBER,
                    209:        .description    = "Multicast",
                    210:        .rxid           = -1,
                    211:        .txid           = RTNL_LINK_MULTICAST,
                    212: },
                    213: {
                    214:        .name           = "ip6pkts",
                    215:        .type           = ATTR_TYPE_COUNTER,
                    216:        .unit           = UNIT_NUMBER,
                    217:        .description    = "Ip6Pkts",
                    218:        .rxid           = RTNL_LINK_IP6_INPKTS,
                    219:        .txid           = RTNL_LINK_IP6_OUTPKTS,
                    220: },
                    221: {
                    222:        .name           = "ip6discards",
                    223:        .type           = ATTR_TYPE_COUNTER,
                    224:        .unit           = UNIT_NUMBER,
                    225:        .description    = "Ip6Discards",
                    226:        .rxid           = RTNL_LINK_IP6_INDISCARDS,
                    227:        .txid           = RTNL_LINK_IP6_OUTDISCARDS,
                    228: },
                    229: {
                    230:        .name           = "ip6octets",
                    231:        .type           = ATTR_TYPE_COUNTER,
                    232:        .unit           = UNIT_BYTE,
                    233:        .description    = "Ip6Octets",
                    234:        .rxid           = RTNL_LINK_IP6_INOCTETS,
                    235:        .txid           = RTNL_LINK_IP6_OUTOCTETS,
                    236: },
                    237: {
                    238:        .name           = "ip6bcastp",
                    239:        .type           = ATTR_TYPE_COUNTER,
                    240:        .unit           = UNIT_NUMBER,
                    241:        .description    = "Ip6 Broadcast Packets",
                    242:        .rxid           = RTNL_LINK_IP6_INBCASTPKTS,
                    243:        .txid           = RTNL_LINK_IP6_OUTBCASTPKTS,
                    244: },
                    245: {
                    246:        .name           = "ip6bcast",
                    247:        .type           = ATTR_TYPE_COUNTER,
                    248:        .unit           = UNIT_BYTE,
                    249:        .description    = "Ip6 Broadcast",
                    250:        .rxid           = RTNL_LINK_IP6_INBCASTOCTETS,
                    251:        .txid           = RTNL_LINK_IP6_OUTBCASTOCTETS,
                    252: },
                    253: {
                    254:        .name           = "ip6mcastp",
                    255:        .type           = ATTR_TYPE_COUNTER,
                    256:        .unit           = UNIT_NUMBER,
                    257:        .description    = "Ip6 Multicast Packets",
                    258:        .rxid           = RTNL_LINK_IP6_INMCASTPKTS,
                    259:        .txid           = RTNL_LINK_IP6_OUTMCASTPKTS,
                    260: },
                    261: {
                    262:        .name           = "ip6mcast",
                    263:        .type           = ATTR_TYPE_COUNTER,
                    264:        .unit           = UNIT_BYTE,
                    265:        .description    = "Ip6 Multicast",
                    266:        .rxid           = RTNL_LINK_IP6_INMCASTOCTETS,
                    267:        .txid           = RTNL_LINK_IP6_OUTMCASTOCTETS,
                    268: },
                    269: {
                    270:        .name           = "ip6noroute",
                    271:        .type           = ATTR_TYPE_COUNTER,
                    272:        .unit           = UNIT_NUMBER,
                    273:        .description    = "Ip6 No Route",
                    274:        .rxid           = RTNL_LINK_IP6_INNOROUTES,
                    275:        .txid           = RTNL_LINK_IP6_OUTNOROUTES,
                    276: },
                    277: {
                    278:        .name           = "ip6forward",
                    279:        .type           = ATTR_TYPE_COUNTER,
                    280:        .unit           = UNIT_NUMBER,
                    281:        .description    = "Ip6 Forwarded",
                    282:        .rxid           = -1,
                    283:        .txid           = RTNL_LINK_IP6_OUTFORWDATAGRAMS,
                    284: },
                    285: {
                    286:        .name           = "ip6delivers",
                    287:        .type           = ATTR_TYPE_COUNTER,
                    288:        .unit           = UNIT_NUMBER,
                    289:        .description    = "Ip6 Delivers",
                    290:        .rxid           = RTNL_LINK_IP6_INDELIVERS,
                    291:        .txid           = -1,
                    292: },
                    293: {
                    294:        .name           = "icmp6",
                    295:        .type           = ATTR_TYPE_COUNTER,
                    296:        .unit           = UNIT_NUMBER,
                    297:        .description    = "ICMPv6",
                    298:        .rxid           = RTNL_LINK_ICMP6_INMSGS,
                    299:        .txid           = RTNL_LINK_ICMP6_OUTMSGS,
                    300: },
                    301: {
                    302:        .name           = "icmp6err",
                    303:        .type           = ATTR_TYPE_COUNTER,
                    304:        .unit           = UNIT_NUMBER,
                    305:        .description    = "ICMPv6 Errors",
                    306:        .rxid           = RTNL_LINK_ICMP6_INERRORS,
                    307:        .txid           = RTNL_LINK_ICMP6_OUTERRORS,
                    308: },
                    309: {
1.1.1.3 ! misho     310:        .name           = "icmp6csumerr",
        !           311:        .type           = ATTR_TYPE_COUNTER,
        !           312:        .unit           = UNIT_NUMBER,
        !           313:        .description    = "ICMPv6 Checksum Errors",
        !           314:        .rxid           = RTNL_LINK_ICMP6_CSUMERRORS,
        !           315:        .txid           = -1,
        !           316: },
        !           317: {
1.1.1.2   misho     318:        .name           = "ip6inhdrerr",
                    319:        .type           = ATTR_TYPE_COUNTER,
                    320:        .unit           = UNIT_NUMBER,
                    321:        .description    = "Ip6 Header Error",
                    322:        .rxid           = RTNL_LINK_IP6_INHDRERRORS,
                    323:        .txid           = -1,
                    324: },
                    325: {
                    326:        .name           = "ip6toobigerr",
                    327:        .type           = ATTR_TYPE_COUNTER,
                    328:        .unit           = UNIT_NUMBER,
                    329:        .description    = "Ip6 Too Big Error",
                    330:        .rxid           = RTNL_LINK_IP6_INTOOBIGERRORS,
                    331:        .txid           = -1,
                    332: },
                    333: {
                    334:        .name           = "ip6trunc",
                    335:        .type           = ATTR_TYPE_COUNTER,
                    336:        .unit           = UNIT_NUMBER,
                    337:        .description    = "Ip6 Truncated Packets",
                    338:        .rxid           = RTNL_LINK_IP6_INTRUNCATEDPKTS,
                    339:        .txid           = -1,
                    340: },
                    341: {
                    342:        .name           = "ip6unkproto",
                    343:        .type           = ATTR_TYPE_COUNTER,
                    344:        .unit           = UNIT_NUMBER,
                    345:        .description    = "Ip6 Unknown Protocol Error",
                    346:        .rxid           = RTNL_LINK_IP6_INUNKNOWNPROTOS,
                    347:        .txid           = -1,
                    348: },
                    349: {
                    350:        .name           = "ip6addrerr",
                    351:        .type           = ATTR_TYPE_COUNTER,
                    352:        .unit           = UNIT_NUMBER,
                    353:        .description    = "Ip6 Address Error",
                    354:        .rxid           = RTNL_LINK_IP6_INADDRERRORS,
                    355:        .txid           = -1,
                    356: },
                    357: {
1.1.1.3 ! misho     358:        .name           = "ip6csumerr",
        !           359:        .type           = ATTR_TYPE_COUNTER,
        !           360:        .unit           = UNIT_NUMBER,
        !           361:        .description    = "Ip6 Checksum Error",
        !           362:        .rxid           = RTNL_LINK_IP6_CSUMERRORS,
        !           363:        .txid           = -1,
        !           364: },
        !           365: {
1.1.1.2   misho     366:        .name           = "ip6reasmtimeo",
                    367:        .type           = ATTR_TYPE_COUNTER,
                    368:        .unit           = UNIT_NUMBER,
                    369:        .description    = "Ip6 Reassembly Timeouts",
                    370:        .rxid           = RTNL_LINK_IP6_REASMTIMEOUT,
                    371:        .txid           = -1,
                    372: },
                    373: {
                    374:        .name           = "ip6fragok",
                    375:        .type           = ATTR_TYPE_COUNTER,
                    376:        .unit           = UNIT_NUMBER,
                    377:        .description    = "Ip6 Reasm/Frag OK",
                    378:        .rxid           = RTNL_LINK_IP6_REASMOKS,
                    379:        .txid           = RTNL_LINK_IP6_FRAGOKS,
                    380: },
                    381: {
                    382:        .name           = "ip6fragfail",
                    383:        .type           = ATTR_TYPE_COUNTER,
                    384:        .unit           = UNIT_NUMBER,
                    385:        .description    = "Ip6 Reasm/Frag Failures",
                    386:        .rxid           = RTNL_LINK_IP6_REASMFAILS,
                    387:        .txid           = RTNL_LINK_IP6_FRAGFAILS,
                    388: },
                    389: {
                    390:        .name           = "ip6fragcreate",
                    391:        .type           = ATTR_TYPE_COUNTER,
                    392:        .unit           = UNIT_NUMBER,
                    393:        .description    = "Ip6 Reasm/Frag Requests",
                    394:        .rxid           = RTNL_LINK_IP6_REASMREQDS,
                    395:        .txid           = RTNL_LINK_IP6_FRAGCREATES,
1.1.1.3 ! misho     396: },
        !           397: {
        !           398:        .name           = "ip6noectpkts",
        !           399:        .type           = ATTR_TYPE_COUNTER,
        !           400:        .unit           = UNIT_NUMBER,
        !           401:        .description    = "Ip6 Non-ECT Packets",
        !           402:        .rxid           = RTNL_LINK_IP6_NOECTPKTS,
        !           403:        .txid           = -1,
        !           404: },
        !           405: {
        !           406:        .name           = "ip6ect1pkts",
        !           407:        .type           = ATTR_TYPE_COUNTER,
        !           408:        .unit           = UNIT_NUMBER,
        !           409:        .description    = "Ip6 ECT(1) Packets",
        !           410:        .rxid           = RTNL_LINK_IP6_ECT1PKTS,
        !           411:        .txid           = -1,
        !           412: },
        !           413: {
        !           414:        .name           = "ip6ect0pkts",
        !           415:        .type           = ATTR_TYPE_COUNTER,
        !           416:        .unit           = UNIT_NUMBER,
        !           417:        .description    = "Ip6 ECT(0) Packets",
        !           418:        .rxid           = RTNL_LINK_IP6_ECT0PKTS,
        !           419:        .txid           = -1,
        !           420: },
        !           421: {
        !           422:        .name           = "ip6cepkts",
        !           423:        .type           = ATTR_TYPE_COUNTER,
        !           424:        .unit           = UNIT_NUMBER,
        !           425:        .description    = "Ip6 CE Packets",
        !           426:        .rxid           = RTNL_LINK_IP6_CEPKTS,
        !           427:        .txid           = -1,
1.1.1.2   misho     428: }
                    429: };
1.1       misho     430: 
1.1.1.2   misho     431: static struct attr_map tc_attrs[] = {
                    432: {
                    433:        .name           = "tc_bytes",
                    434:        .type           = ATTR_TYPE_COUNTER,
                    435:        .unit           = UNIT_BYTE,
                    436:        .description    = "Bytes",
                    437:        .rxid           = -1,
                    438:        .txid           = RTNL_TC_BYTES,
                    439: },
                    440: {
                    441:        .name           = "tc_packets",
                    442:        .type           = ATTR_TYPE_COUNTER,
                    443:        .unit           = UNIT_NUMBER,
                    444:        .description    = "Packets",
                    445:        .rxid           = -1,
                    446:        .txid           = RTNL_TC_PACKETS,
                    447: },
                    448: {
                    449:        .name           = "tc_overlimits",
                    450:        .type           = ATTR_TYPE_COUNTER,
                    451:        .unit           = UNIT_NUMBER,
                    452:        .description    = "Overlimits",
                    453:        .rxid           = -1,
                    454:        .txid           = RTNL_TC_OVERLIMITS,
                    455: },
                    456: {
                    457:        .name           = "tc_drop",
                    458:        .type           = ATTR_TYPE_COUNTER,
                    459:        .unit           = UNIT_NUMBER,
                    460:        .description    = "Dropped",
                    461:        .rxid           = -1,
                    462:        .txid           = RTNL_TC_DROPS,
                    463: },
                    464: {
                    465:        .name           = "tc_bps",
                    466:        .type           = ATTR_TYPE_RATE,
                    467:        .unit           = UNIT_BYTE,
                    468:        .description    = "Byte Rate/s",
                    469:        .rxid           = -1,
                    470:        .txid           = RTNL_TC_RATE_BPS,
                    471: },
                    472: {
                    473:        .name           = "tc_pps",
                    474:        .type           = ATTR_TYPE_RATE,
                    475:        .unit           = UNIT_NUMBER,
                    476:        .description    = "Packet Rate/s",
                    477:        .rxid           = -1,
                    478:        .txid           = RTNL_TC_RATE_PPS,
                    479: },
                    480: {
                    481:        .name           = "tc_qlen",
                    482:        .type           = ATTR_TYPE_RATE,
                    483:        .unit           = UNIT_NUMBER,
                    484:        .description    = "Queue Length",
                    485:        .rxid           = -1,
                    486:        .txid           = RTNL_TC_QLEN,
                    487: },
                    488: {
                    489:        .name           = "tc_backlog",
                    490:        .type           = ATTR_TYPE_RATE,
                    491:        .unit           = UNIT_NUMBER,
                    492:        .description    = "Backlog",
                    493:        .rxid           = -1,
                    494:        .txid           = RTNL_TC_BACKLOG,
                    495: },
                    496: {
                    497:        .name           = "tc_requeues",
                    498:        .type           = ATTR_TYPE_COUNTER,
                    499:        .unit           = UNIT_NUMBER,
                    500:        .description    = "Requeues",
                    501:        .rxid           = -1,
                    502:        .txid           = RTNL_TC_REQUEUES,
                    503: }
                    504: };
                    505: 
                    506: struct rdata {
1.1.1.3 ! misho     507:        struct nl_cache *       class_cache;
1.1.1.2   misho     508:        struct element *        parent;
                    509:        int                     level;
1.1       misho     510: };
                    511: 
1.1.1.2   misho     512: static struct nl_sock *sock;
1.1.1.3 ! misho     513: static struct nl_cache *link_cache, *qdisc_cache;
1.1.1.2   misho     514: 
                    515: static void update_tc_attrs(struct element *e, struct rtnl_tc *tc)
1.1       misho     516: {
1.1.1.2   misho     517:        int i;
1.1       misho     518: 
1.1.1.2   misho     519:        for (i = 0; i < ARRAY_SIZE(tc_attrs); i++) {
                    520:                uint64_t c_tx = rtnl_tc_get_stat(tc, tc_attrs[i].txid);
                    521:                attr_update(e, tc_attrs[i].attrid, 0, c_tx, UPDATE_FLAG_TX);
                    522:        }
                    523: }
1.1       misho     524: 
1.1.1.2   misho     525: static void update_tc_infos(struct element *e, struct rtnl_tc *tc)
                    526: {
                    527:        char buf[64];
1.1       misho     528: 
1.1.1.2   misho     529:        snprintf(buf, sizeof(buf), "%u", rtnl_tc_get_mtu(tc));
                    530:        element_update_info(e, "MTU", buf);
1.1       misho     531: 
1.1.1.2   misho     532:        snprintf(buf, sizeof(buf), "%u", rtnl_tc_get_mpu(tc));
                    533:        element_update_info(e, "MPU", buf);
1.1       misho     534: 
1.1.1.2   misho     535:        snprintf(buf, sizeof(buf), "%u", rtnl_tc_get_overhead(tc));
                    536:        element_update_info(e, "Overhead", buf);
1.1       misho     537: 
1.1.1.2   misho     538:        snprintf(buf, sizeof(buf), "%#x", rtnl_tc_get_handle(tc));
                    539:        element_update_info(e, "Id", buf);
1.1       misho     540: 
1.1.1.2   misho     541:        snprintf(buf, sizeof(buf), "%#x", rtnl_tc_get_parent(tc));
                    542:        element_update_info(e, "Parent", buf);
1.1       misho     543: 
                    544: }
                    545: 
1.1.1.2   misho     546: static void handle_qdisc(struct nl_object *obj, void *);
                    547: static void find_classes(uint32_t, struct rdata *);
1.1.1.3 ! misho     548: static void find_qdiscs(int, uint32_t, struct rdata *);
1.1.1.2   misho     549: 
                    550: static struct element *handle_tc_obj(struct rtnl_tc *tc, const char *prefix,
1.1.1.3 ! misho     551:                                     const struct rdata *rdata)
1.1       misho     552: {
1.1.1.2   misho     553:        char buf[IFNAME_MAX], name[IFNAME_MAX];
                    554:        uint32_t id = rtnl_tc_get_handle(tc);
                    555:        struct element *e;
                    556: 
                    557:        rtnl_tc_handle2str(id, buf, sizeof(buf));
                    558:        snprintf(name, sizeof(name), "%s %s (%s)",
                    559:                 prefix, buf, rtnl_tc_get_kind(tc));
                    560: 
1.1.1.3 ! misho     561:        if (!rdata || !rdata->parent)
        !           562:                BUG();
        !           563: 
        !           564:        if (!(e = element_lookup(grp, name, id, rdata->parent, ELEMENT_CREAT)))
1.1.1.2   misho     565:                return NULL;
                    566: 
                    567:        if (e->e_flags & ELEMENT_FLAG_CREATED) {
1.1.1.3 ! misho     568:                e->e_level = rdata->level;
1.1       misho     569: 
1.1.1.2   misho     570:                if (element_set_key_attr(e, "tc_bytes", "tc_packets") ||
                    571:                    element_set_usage_attr(e, "tc_bytes"))
                    572:                        BUG();
1.1       misho     573: 
1.1.1.2   misho     574:                update_tc_infos(e, tc);
                    575: 
                    576:                e->e_flags &= ~ELEMENT_FLAG_CREATED;
                    577:        }
                    578: 
                    579:        update_tc_attrs(e, tc);
                    580: 
                    581:        element_notify_update(e, NULL);
                    582:        element_lifesign(e, 1);
                    583: 
                    584:        return e;
1.1       misho     585: }
                    586: 
1.1.1.2   misho     587: static void handle_cls(struct nl_object *obj, void *arg)
                    588: {
                    589:        struct rtnl_cls *cls = (struct rtnl_cls *) obj;
                    590:        struct rdata *rdata = arg;
                    591: 
                    592:        handle_tc_obj((struct rtnl_tc *) cls, "cls", rdata);
                    593: }
1.1       misho     594: 
1.1.1.2   misho     595: static void handle_class(struct nl_object *obj, void *arg)
1.1       misho     596: {
1.1.1.2   misho     597:        struct rtnl_tc *tc = (struct rtnl_tc *) obj;
                    598:        struct element *e;
1.1.1.3 ! misho     599:        const struct rdata *rdata = arg;
1.1.1.2   misho     600:        struct rdata ndata = {
1.1.1.3 ! misho     601:                .class_cache = rdata->class_cache,
1.1.1.2   misho     602:                .level = rdata->level + 1,
                    603:        };
1.1       misho     604: 
1.1.1.2   misho     605:        if (!(e = handle_tc_obj(tc, "class", rdata)))
                    606:                return;
1.1       misho     607: 
1.1.1.2   misho     608:        ndata.parent = e;
1.1       misho     609: 
1.1.1.2   misho     610:        if (!strcmp(rtnl_tc_get_kind(tc), "htb"))
                    611:                element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));
1.1       misho     612: 
1.1.1.2   misho     613:        find_classes(rtnl_tc_get_handle(tc), &ndata);
1.1.1.3 ! misho     614:        find_qdiscs(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);
1.1.1.2   misho     615: }
                    616: 
1.1.1.3 ! misho     617: static void find_qdiscs(int ifindex, uint32_t parent, struct rdata *rdata)
1.1.1.2   misho     618: {
                    619:        struct rtnl_qdisc *filter;
                    620: 
                    621:        if (!(filter = rtnl_qdisc_alloc()))
1.1       misho     622:                return;
                    623: 
1.1.1.2   misho     624:        rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
1.1.1.3 ! misho     625:        rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex);
1.1       misho     626: 
1.1.1.2   misho     627:        nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
                    628:                                handle_qdisc, rdata);
1.1       misho     629: 
1.1.1.2   misho     630:        rtnl_qdisc_put(filter);
1.1       misho     631: }
                    632: 
1.1.1.2   misho     633: static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata)
1.1       misho     634: {
1.1.1.2   misho     635:        struct nl_cache *cls_cache;
                    636: 
                    637:        if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0)
                    638:                return;
                    639: 
                    640:        nl_cache_foreach(cls_cache, handle_cls, rdata);
1.1       misho     641: 
1.1.1.2   misho     642:        nl_cache_free(cls_cache);
                    643: }
1.1       misho     644: 
1.1.1.2   misho     645: static void find_classes(uint32_t parent, struct rdata *rdata)
                    646: {
                    647:        struct rtnl_class *filter;
1.1       misho     648: 
1.1.1.2   misho     649:        if (!(filter = rtnl_class_alloc()))
1.1       misho     650:                return;
                    651: 
1.1.1.2   misho     652:        rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
1.1       misho     653: 
1.1.1.3 ! misho     654:        nl_cache_foreach_filter(rdata->class_cache, OBJ_CAST(filter),
1.1.1.2   misho     655:                                handle_class, rdata);
                    656: 
                    657:        rtnl_class_put(filter);
1.1       misho     658: }
                    659: 
1.1.1.2   misho     660: static void handle_qdisc(struct nl_object *obj, void *arg)
1.1       misho     661: {
1.1.1.2   misho     662:        struct rtnl_tc *tc = (struct rtnl_tc *) obj;
                    663:        struct element *e;
1.1.1.3 ! misho     664:        const struct rdata *rdata = arg;
1.1.1.2   misho     665:        struct rdata ndata = {
1.1.1.3 ! misho     666:                .class_cache = rdata->class_cache,
1.1.1.2   misho     667:                .level = rdata->level + 1,
1.1       misho     668:        };
                    669: 
1.1.1.2   misho     670:        if (!(e = handle_tc_obj(tc, "qdisc", rdata)))
1.1       misho     671:                return;
                    672: 
1.1.1.2   misho     673:        ndata.parent = e;
1.1       misho     674: 
1.1.1.2   misho     675:        find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);
                    676: 
                    677:        if (rtnl_tc_get_parent(tc) == TC_H_ROOT) {
                    678:                find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata);
                    679:                find_classes(TC_H_ROOT, &ndata);
                    680:        }
                    681: 
                    682:        find_classes(rtnl_tc_get_handle(tc), &ndata);
1.1       misho     683: }
                    684: 
1.1.1.2   misho     685: static void handle_tc(struct element *e, struct rtnl_link *link)
1.1       misho     686: {
                    687:        struct rtnl_qdisc *qdisc;
1.1.1.3 ! misho     688:        struct nl_cache *class_cache;
1.1.1.2   misho     689:        int ifindex = rtnl_link_get_ifindex(link);
                    690:        struct rdata rdata = {
1.1       misho     691:                .level = 1,
1.1.1.2   misho     692:                .parent = e,
1.1       misho     693:        };
                    694: 
1.1.1.2   misho     695:        if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
1.1       misho     696:                return;
                    697: 
1.1.1.3 ! misho     698:        rdata.class_cache = class_cache;
        !           699: 
1.1.1.2   misho     700:        qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
                    701:        if (qdisc) {
                    702:                handle_qdisc(OBJ_CAST(qdisc), &rdata);
                    703:                rtnl_qdisc_put(qdisc);
                    704:        }
                    705: 
                    706:        qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
                    707:        if (qdisc) {
                    708:                handle_qdisc(OBJ_CAST(qdisc), &rdata);
                    709:                rtnl_qdisc_put(qdisc);
                    710:        }
                    711: 
                    712:        qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
                    713:        if (qdisc) {
                    714:                handle_qdisc(OBJ_CAST(qdisc), &rdata);
                    715:                rtnl_qdisc_put(qdisc);
                    716:        }
                    717: 
                    718:        nl_cache_free(class_cache);
                    719: }
                    720: 
                    721: static void update_link_infos(struct element *e, struct rtnl_link *link)
                    722: {
                    723:        char buf[64];
                    724: 
                    725:        snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link));
                    726:        element_update_info(e, "MTU", buf);
                    727: 
                    728:        rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf));
                    729:        element_update_info(e, "Flags", buf);
                    730: 
                    731:        rtnl_link_operstate2str(rtnl_link_get_operstate(link),
                    732:                                buf, sizeof(buf));
                    733:        element_update_info(e, "Operstate", buf);
                    734: 
                    735:        snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link));
                    736:        element_update_info(e, "IfIndex", buf);
                    737: 
                    738:        nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf));
                    739:        element_update_info(e, "Address", buf);
                    740: 
                    741:        nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf));
                    742:        element_update_info(e, "Broadcast", buf);
                    743: 
                    744:        rtnl_link_mode2str(rtnl_link_get_linkmode(link),
                    745:                           buf, sizeof(buf));
                    746:        element_update_info(e, "Mode", buf);
                    747: 
                    748:        snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link));
                    749:        element_update_info(e, "TXQlen", buf);
1.1       misho     750: 
1.1.1.2   misho     751:        nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf));
                    752:        element_update_info(e, "Family", buf);
1.1       misho     753: 
1.1.1.2   misho     754:        element_update_info(e, "Alias",
                    755:                rtnl_link_get_ifalias(link) ? : "");
                    756: 
                    757:        element_update_info(e, "Qdisc",
                    758:                rtnl_link_get_qdisc(link) ? : "");
                    759: 
                    760:        if (rtnl_link_get_link(link)) {
                    761:                snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link));
                    762:                element_update_info(e, "SlaveOfIndex", buf);
                    763:        }
1.1       misho     764: }
                    765: 
1.1.1.2   misho     766: static void do_link(struct nl_object *obj, void *arg)
1.1       misho     767: {
1.1.1.2   misho     768:        struct rtnl_link *link = (struct rtnl_link *) obj;
                    769:        struct element *e, *e_parent = NULL;
                    770:        int i, master_ifindex;
1.1       misho     771: 
1.1.1.2   misho     772:        if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) {
                    773:                /* FIXME: delete element */
1.1       misho     774:                return;
1.1.1.2   misho     775:        }
1.1       misho     776: 
1.1.1.2   misho     777:        /* Check if the interface is a slave of another interface */
                    778:        if ((master_ifindex = rtnl_link_get_link(link))) {
                    779:                char parent[IFNAMSIZ+1];
                    780: 
                    781:                rtnl_link_i2name(link_cache, master_ifindex,
                    782:                                 parent, sizeof(parent));
1.1       misho     783: 
1.1.1.2   misho     784:                e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0);
                    785:        }
1.1       misho     786: 
1.1.1.2   misho     787:        if (!(e = element_lookup(grp, rtnl_link_get_name(link),
                    788:                                 rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT)))
1.1       misho     789:                return;
                    790: 
1.1.1.2   misho     791:        if (e->e_flags & ELEMENT_FLAG_CREATED) {
                    792:                if (e->e_parent)
                    793:                        e->e_level = e->e_parent->e_level + 1;
                    794: 
                    795:                if (element_set_key_attr(e, "bytes", "packets") ||
                    796:                    element_set_usage_attr(e, "bytes"))
                    797:                        BUG();
1.1       misho     798: 
1.1.1.2   misho     799:                /* FIXME: Update link infos every 1s or so */
                    800:                update_link_infos(e, link);
                    801: 
                    802:                e->e_flags &= ~ELEMENT_FLAG_CREATED;
                    803:        }
                    804: 
                    805:        for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
                    806:                struct attr_map *m = &link_attrs[i];
                    807:                uint64_t c_rx = 0, c_tx = 0;
                    808:                int flags = 0;
                    809: 
                    810:                if (m->rxid >= 0) {
                    811:                        c_rx = rtnl_link_get_stat(link, m->rxid);
                    812:                        flags |= UPDATE_FLAG_RX;
                    813:                }
                    814: 
                    815:                if (m->txid >= 0) {
                    816:                        c_tx = rtnl_link_get_stat(link, m->txid);
                    817:                        flags |= UPDATE_FLAG_TX;
                    818:                }
1.1       misho     819: 
1.1.1.2   misho     820:                attr_update(e, m->attrid, c_rx, c_tx, flags);
                    821:        }
1.1       misho     822: 
1.1.1.3 ! misho     823:        if (!c_notc && qdisc_cache)
1.1.1.2   misho     824:                handle_tc(e, link);
                    825: 
                    826:        element_notify_update(e, NULL);
                    827:        element_lifesign(e, 1);
1.1       misho     828: }
                    829: 
                    830: static void netlink_read(void)
                    831: {
1.1.1.2   misho     832:        int err;
1.1       misho     833: 
1.1.1.2   misho     834:        if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) {
                    835:                fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err));
                    836:                goto disable;
1.1       misho     837:        }
                    838: 
1.1.1.3 ! misho     839:        if (qdisc_cache &&
        !           840:            (err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
1.1.1.2   misho     841:                fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
                    842:                goto disable;
                    843:        }
                    844: 
                    845:        nl_cache_foreach(link_cache, do_link, NULL);
                    846: 
                    847:        return;
                    848: 
                    849: disable:
                    850:        netlink_ops.m_flags &= ~BMON_MODULE_ENABLED;
1.1       misho     851: }
                    852: 
                    853: static void netlink_shutdown(void)
                    854: {
1.1.1.2   misho     855:        nl_cache_free(link_cache);
                    856:        nl_cache_free(qdisc_cache);
                    857:        nl_socket_free(sock);
1.1       misho     858: }
                    859: 
1.1.1.3 ! misho     860: static void netlink_use_bit(struct attr_map *map, const int size)
        !           861: {
        !           862:        if(cfg_getbool(cfg, "use_bit")) {
        !           863:                for(int i = 0; i < size; ++i) {
        !           864:                        if(!strcmp(map[i].description, "Bytes")) {
        !           865:                                map[i].description = "Bits";
        !           866:                        }
        !           867:                }
        !           868:        }
        !           869: }
        !           870: 
1.1.1.2   misho     871: static int netlink_do_init(void)
1.1       misho     872: {
1.1.1.3 ! misho     873:        int err;
1.1.1.2   misho     874: 
                    875:        if (!(sock = nl_socket_alloc())) {
                    876:                fprintf(stderr, "Unable to allocate netlink socket\n");
                    877:                goto disable;
                    878:        }
                    879: 
                    880:        if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
                    881:                fprintf(stderr, "Unable to connect netlink socket: %s\n", nl_geterror(err));
                    882:                goto disable;
                    883:        }
                    884: 
                    885:        if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) {
                    886:                fprintf(stderr, "Unable to allocate link cache: %s\n", nl_geterror(err));
                    887:                goto disable;
                    888:        }
                    889: 
                    890:        if ((err = rtnl_qdisc_alloc_cache(sock, &qdisc_cache)) < 0) {
1.1.1.3 ! misho     891:                fprintf(stderr, "Warning: Unable to allocate qdisc cache: %s\n", nl_geterror(err));
        !           892:                fprintf(stderr, "Disabling QoS statistics.\n");
        !           893:                qdisc_cache = NULL;
1.1.1.2   misho     894:        }
                    895: 
1.1.1.3 ! misho     896:        netlink_use_bit(link_attrs, ARRAY_SIZE(link_attrs));
        !           897:        netlink_use_bit(tc_attrs, ARRAY_SIZE(tc_attrs));
1.1.1.2   misho     898:        if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)) ||
                    899:            attr_map_load(tc_attrs, ARRAY_SIZE(tc_attrs)))
                    900:                BUG();
1.1       misho     901: 
1.1.1.2   misho     902:        if (!(grp = group_lookup(DEFAULT_GROUP, GROUP_CREATE)))
                    903:                BUG();
                    904: 
                    905:        return 0;
                    906: 
                    907: disable:
                    908:        return -EOPNOTSUPP;
1.1       misho     909: }
                    910: 
                    911: static int netlink_probe(void)
                    912: {
1.1.1.2   misho     913:        struct nl_sock *sock;
                    914:        struct nl_cache *lc;
                    915:        int ret = 0;
                    916: 
                    917:        if (!(sock = nl_socket_alloc()))
1.1       misho     918:                return 0;
1.1.1.3 ! misho     919: 
1.1.1.2   misho     920:        if (nl_connect(sock, NETLINK_ROUTE) < 0)
1.1       misho     921:                return 0;
1.1.1.3 ! misho     922: 
1.1.1.2   misho     923:        if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &lc) == 0) {
                    924:                nl_cache_free(lc);
                    925:                ret = 1;
1.1       misho     926:        }
                    927: 
1.1.1.2   misho     928:        nl_socket_free(sock);
1.1.1.3 ! misho     929: 
1.1.1.2   misho     930:        return ret;
1.1       misho     931: }
                    932: 
                    933: static void print_help(void)
                    934: {
                    935:        printf(
                    936:        "netlink - Netlink statistic collector for Linux\n" \
                    937:        "\n" \
                    938:        "  Powerful statistic collector for Linux using netlink sockets\n" \
                    939:        "  to collect link and traffic control statistics.\n" \
                    940:        "  Author: Thomas Graf <tgraf@suug.ch>\n" \
                    941:        "\n" \
                    942:        "  Options:\n" \
1.1.1.2   misho     943:        "    notc           Do not collect traffic control statistics\n");
1.1       misho     944: }
                    945: 
1.1.1.2   misho     946: static void netlink_parse_opt(const char *type, const char *value)
                    947: {
                    948:        if (!strcasecmp(type, "notc"))
                    949:                c_notc = 1;
                    950:        else if (!strcasecmp(type, "help")) {
                    951:                print_help();
                    952:                exit(0);
1.1       misho     953:        }
                    954: }
                    955: 
1.1.1.2   misho     956: static struct bmon_module netlink_ops = {
                    957:        .m_name         = "netlink",
                    958:        .m_flags        = BMON_MODULE_DEFAULT,
                    959:        .m_do           = netlink_read,
                    960:        .m_shutdown     = netlink_shutdown,
                    961:        .m_parse_opt    = netlink_parse_opt,
                    962:        .m_probe        = netlink_probe,
                    963:        .m_init         = netlink_do_init,
1.1       misho     964: };
                    965: 
                    966: static void __init netlink_init(void)
                    967: {
1.1.1.2   misho     968:        input_register(&netlink_ops);
1.1       misho     969: }
                    970: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>