Cint recipes

Small Cint programs that read state through the SDK API on a Trident 3 SONiC switch. All of them are read-only: they call only *_get and *_traverse functions and change nothing on the switch. Each starts with cint_reset(); so it can be run again, and ends by printing DONE <name>; if that line is missing, the program did not run to the end. See Cint: the C interpreter for how Cint runs and The Cint language for the language.

Copy a program to /root in the syncd container and run it from the host (see Cint: the C interpreter for why not /tmp):

Hardware-validated

$ sudo docker cp hello_info.c syncd:/root/
$ bcmcmd -t 120 "cint /root/hello_info.c"

or from an interactive bcmsh session with cint /root/hello_info.c.

Programs that walk a table hold that table’s lock while they run, so syncd waits to update it. They print only the first entries, but they still visit every entry; on a switch with a large L2 or route table, run them when a short delay in programming is acceptable.

Chip identity

bcm_info_get returns the PCI vendor and device ID and the revision. The Trident 3 below reports device 0xb870; other members of the family report other IDs, for example 0xb873 in the capture in the cint reference. The structure printed by print info ends with per-die arrays that are all zero on Trident 3.

hello_info.c
/*
 * hello_info.c - print the chip identity with bcm_info_get().
 * Read-only.  Run:  cint /root/hello_info.c
 */
cint_reset();

int hello_info()
{
    int unit = 0;
    int rv;
    bcm_info_t info;

    rv = bcm_info_get(unit, &info);
    if (rv != BCM_E_NONE) {
        printf("bcm_info_get failed: %d (%s)\n", rv, bcm_errmsg(rv));
        return rv;
    }
    printf("vendor 0x%04x device 0x%04x revision 0x%02x\n",
           info.vendor, info.device, info.revision);
    print info;
    return 0;
}

hello_info();
printf("DONE hello_info\n");

Hardware-validated

drivshell> cint /root/hello_info.c
vendor 0x14e4 device 0xb870 revision 0x01
bcm_info_t info = {
    unsigned int vendor = 5348 (0x14e4)
    unsigned int device = 47216 (0xb870)
    unsigned int revision = 1 (0x1)
    unsigned int capability = 13 (0xd)
    int num_pipes = 2 (0x2)
    int num_pp_pipes = 0 (0x0)
    int num_buffers = 0 (0x0)
    int num_instances_per_pp_pipe = 0 (0x0)
    unsigned int package_rev_id = 0 (0x0)
    unsigned int interposer_rev_id = 0 (0x0)
    int dies_num = 0 (0x0)
    unsigned int[16] die_dev_id = {
        unsigned int die_dev_id[0] = 0 (0x0)
        unsigned int die_dev_id[1] = 0 (0x0)
        unsigned int die_dev_id[2] = 0 (0x0)
        unsigned int die_dev_id[3] = 0 (0x0)
        unsigned int die_dev_id[4] = 0 (0x0)
        unsigned int die_dev_id[5] = 0 (0x0)
        unsigned int die_dev_id[6] = 0 (0x0)
        unsigned int die_dev_id[7] = 0 (0x0)
        unsigned int die_dev_id[8] = 0 (0x0)
        unsigned int die_dev_id[9] = 0 (0x0)
        unsigned int die_dev_id[10] = 0 (0x0)
        unsigned int die_dev_id[11] = 0 (0x0)
        unsigned int die_dev_id[12] = 0 (0x0)
        unsigned int die_dev_id[13] = 0 (0x0)
        unsigned int die_dev_id[14] = 0 (0x0)
        unsigned int die_dev_id[15] = 0 (0x0)
...

Port status

One line per front-panel port with the admin state, link state, speed and untagged VLAN. Port numbers are SDK logical port numbers, as shown by ps; see Ports and port bitmaps.

port_status.c
/*
 * port_status.c - one line per front-panel port: enable, link, speed and
 * untagged VLAN.  Read-only.  Run:  cint /root/port_status.c
 */
cint_reset();

int ps_show(int unit, bcm_port_t port)
{
    int enable = -1;
    int link = -1;
    int speed = -1;
    bcm_vlan_t pvid = 0;
    int vid;
    int rv;

    rv = bcm_port_enable_get(unit, port, &enable);
    if (rv != BCM_E_NONE) {
        printf("port %3d: bcm_port_enable_get: %s\n", port, bcm_errmsg(rv));
        return rv;
    }
    bcm_port_link_status_get(unit, port, &link);
    bcm_port_speed_get(unit, port, &speed);
    bcm_port_untagged_vlan_get(unit, port, &pvid);
    vid = pvid;
    printf("port %3d: enable %d link %d speed %6d pvid %4d\n",
           port, enable, link, speed, vid);
    return 0;
}

int ps_main()
{
    int unit = 0;
    int rv;
    int count = 0;
    bcm_port_t port;
    bcm_pbmp_t pbm;
    bcm_port_config_t config;

    bcm_port_config_t_init(&config);
    rv = bcm_port_config_get(unit, &config);
    if (rv != BCM_E_NONE) {
        printf("bcm_port_config_get failed: %s\n", bcm_errmsg(rv));
        return rv;
    }
    pbm = config.port;
    printf("front-panel ports: ${pbm}\n");
    BCM_PBMP_ITER(pbm, port) {
        ps_show(unit, port);
        count++;
    }
    printf("%d ports\n", count);
    return 0;
}

ps_main();
printf("DONE port_status\n");

Hardware-validated

drivshell> cint /root/port_status.c
front-panel ports: { 1 5 9 10 11 12 13 17 21 25 29 33 37 41 45 49 53 57 61 66 67 71 75 79 83 87 91 95 99 103 107 111 115 119 123 127 }
port   1: enable 0 link 0 speed 100000 pvid    1
port   5: enable 0 link 0 speed 100000 pvid    1
port   9: enable 1 link 1 speed  10000 pvid    1
port  10: enable 1 link 1 speed  10000 pvid    1
port  11: enable 1 link 1 speed  10000 pvid    1
port  12: enable 1 link 1 speed  10000 pvid  902
port  13: enable 0 link 0 speed 100000 pvid    1
port  17: enable 0 link 0 speed 100000 pvid    1
port  21: enable 0 link 0 speed 100000 pvid    1
port  25: enable 0 link 0 speed 100000 pvid    1
port  29: enable 0 link 0 speed 100000 pvid    1
port  33: enable 0 link 0 speed 100000 pvid    1
port  37: enable 0 link 0 speed 100000 pvid    1
port  41: enable 0 link 0 speed 100000 pvid    1
port  45: enable 0 link 0 speed 100000 pvid    1
port  49: enable 0 link 0 speed 100000 pvid    1
port  53: enable 0 link 0 speed 100000 pvid    1
port  57: enable 0 link 0 speed 100000 pvid    1
port  61: enable 0 link 0 speed 100000 pvid    1
port  66: enable 0 link 0 speed  10000 pvid    1
port  67: enable 0 link 0 speed 100000 pvid    1
port  71: enable 0 link 0 speed 100000 pvid    1
port  75: enable 0 link 0 speed 100000 pvid    1
port  79: enable 0 link 0 speed 100000 pvid    1
port  83: enable 0 link 0 speed 100000 pvid    1
port  87: enable 0 link 0 speed 100000 pvid    1
port  91: enable 0 link 0 speed 100000 pvid    1
port  95: enable 0 link 0 speed 100000 pvid    1
port  99: enable 0 link 0 speed 100000 pvid    1
port 103: enable 0 link 0 speed 100000 pvid    1
port 107: enable 0 link 0 speed 100000 pvid    1
port 111: enable 0 link 0 speed 100000 pvid    1
port 115: enable 1 link 1 speed 100000 pvid    1
port 119: enable 1 link 1 speed 100000 pvid    1
port 123: enable 0 link 0 speed 100000 pvid    1
port 127: enable 0 link 0 speed 100000 pvid    1
36 ports
DONE port_status

Port counters

Reads 64-bit counters of one port with bcm_stat_get. The port number is the first argument; without one, port 1 is read. These are the SDK’s counters, the same ones show counters reads, so they are not reset by sonic-clear counters.

port_counters.c
/*
 * port_counters.c - read a few SNMP-style counters of one port with
 * bcm_stat_get().  Read-only.
 * Run:  cint /root/port_counters.c [<logical port>]     (default: port 1)
 */
cint_reset();

int pc_atoi(char *s)
{
    int i = 0;
    int v = 0;
    int c;

    while (1) {
        c = s[i];
        if (c < '0' || c > '9') {
            break;
        }
        v = v * 10 + (c - '0');
        i++;
    }
    return v;
}

int pc_show(int unit, bcm_port_t port, bcm_stat_val_t stat, char *name)
{
    uint64 val;
    int rv;

    COMPILER_64_ZERO(&val);
    rv = bcm_stat_get(unit, port, stat, &val);
    if (rv != BCM_E_NONE) {
        printf("  %-22s error %d (%s)\n", name, rv, bcm_errmsg(rv));
        return rv;
    }
    printf("  %-22s ${val}  hi %u lo %u\n", name,
           COMPILER_64_HI(&val), COMPILER_64_LO(&val));
    return 0;
}

int pc_main()
{
    int unit = 0;
    bcm_port_t port = 1;

    if (ARGC > 0) {
        port = pc_atoi(ARGV[0]);
    }
    printf("port %d\n", port);
    pc_show(unit, port, snmpIfHCInOctets, "snmpIfHCInOctets");
    pc_show(unit, port, snmpIfHCInUcastPkts, "snmpIfHCInUcastPkts");
    pc_show(unit, port, snmpIfInErrors, "snmpIfInErrors");
    pc_show(unit, port, snmpIfInDiscards, "snmpIfInDiscards");
    pc_show(unit, port, snmpIfHCOutOctets, "snmpIfHCOutOctets");
    pc_show(unit, port, snmpIfHCOutUcastPkts, "snmpIfHCOutUcastPkts");
    pc_show(unit, port, snmpIfOutErrors, "snmpIfOutErrors");
    pc_show(unit, port, snmpIfOutDiscards, "snmpIfOutDiscards");
    return 0;
}

pc_main();
printf("DONE port_counters\n");

Hardware-validated

drivshell> cint /root/port_counters.c 1
port 1
  snmpIfHCInOctets       {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfHCInUcastPkts    {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfInErrors         {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfInDiscards       {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfHCOutOctets      {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfHCOutUcastPkts   {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfOutErrors        {0x00000000 0x00000000}  hi 0 lo 0
  snmpIfOutDiscards      {0x00000000 0x00000000}  hi 0 lo 0
DONE port_counters

L3 table usage

How full the route, host, next-hop and interface tables are, from bcm_l3_info. l3 info shows similar numbers.

l3_info.c
/*
 * l3_info.c - L3 table sizes and usage from bcm_l3_info().
 * Read-only.  Run:  cint /root/l3_info.c
 */
cint_reset();

int li_main()
{
    int unit = 0;
    int rv;
    bcm_l3_info_t info;

    rv = bcm_l3_info(unit, &info);
    if (rv != BCM_E_NONE) {
        printf("bcm_l3_info failed: %s\n", bcm_errmsg(rv));
        return rv;
    }
    printf("routes  used %d of %d\n", info.l3info_used_route, info.l3info_max_route);
    printf("hosts   used %d of %d\n", info.l3info_used_host, info.l3info_max_host);
    printf("egress  used %d of %d\n", info.l3info_used_nexthop, info.l3info_max_nexthop);
    printf("intf    used %d of %d\n", info.l3info_used_intf, info.l3info_max_intf);
    print info;
    return 0;
}

li_main();
printf("DONE l3_info\n");

Hardware-validated

drivshell> cint /root/l3_info.c
routes  used 6 of 32768
hosts   used 3 of 16384
egress  used 7 of 65536
intf    used 6 of 16383
bcm_l3_info_t info = {
    int l3info_max_vrf = 4095 (0xfff)
    int l3info_used_vrf = -1 (0xffffffff)
    int l3info_max_intf = 16383 (0x3fff)
    int l3info_max_intf_group = 4095 (0xfff)
    int l3info_max_host = 16384 (0x4000)
    int l3info_max_route = 32768 (0x8000)
    int l3info_max_ecmp_groups = 4096 (0x1000)
    int l3info_max_ecmp = 128 (0x80)
    int l3info_max_ecmp_failover_size = 0 (0x0)
    int l3info_used_intf = 6 (0x6)
    int l3info_used_host = 3 (0x3)
    int l3info_used_route = 6 (0x6)
    int l3info_max_lpm_block = 0 (0x0)
    int l3info_used_lpm_block = 0 (0x0)
    int l3info_max_l3 = 16384 (0x4000)
    int l3info_max_defip = 16384 (0x4000)
    int l3info_used_l3 = 3 (0x3)
    int l3info_used_defip = 6 (0x6)
    int l3info_max_nexthop = 65536 (0x10000)
    int l3info_used_nexthop = 7 (0x7)
    int l3info_max_tunnel_init = 4096 (0x1000)
    int l3info_used_tunnel_init = 0 (0x0)
    int l3info_max_tunnel_term = 2048 (0x800)
    int l3info_used_tunnel_term = 0 (0x0)
    int l3info_used_host_ip4 = 1 (0x1)
    int l3info_used_host_ip6 = 2 (0x2)
}
DONE l3_info

Routes

Walks the IPv4 and then the IPv6 route table with bcm_l3_route_traverse and prints the first 20 of each. The third and fourth arguments of bcm_l3_route_traverse are the first and last position in the walk, counted from 0, not table indices; a route with several ECMP paths may count once per path. The intf column is the egress object or ECMP group, as in l3 defip show. IPv6 addresses print as eight full groups (fe80:0000:0000:…), without :: shortening.

l3_routes.c
/*
 * l3_routes.c - print the first routes of the IPv4 and IPv6 route tables
 * with bcm_l3_route_traverse() and a Cint callback.  Read-only.
 * Run:  cint /root/l3_routes.c
 */
cint_reset();

int lr_seen = 0;

int lr_v4_cb(int unit, int index, bcm_l3_route_t *info, void *user_data)
{
    bcm_ip_t net = info->l3a_subnet;
    bcm_ip_t mask = info->l3a_ip_mask;
    int vrf = info->l3a_vrf;
    int intf = info->l3a_intf;
    int flags = info->l3a_flags;

    lr_seen++;
    printf("v4 %3d vrf %d ${net} mask ${mask} intf %d flags 0x%x\n",
           index, vrf, intf, flags);
    return BCM_E_NONE;
}

int lr_v6_cb(int unit, int index, bcm_l3_route_t *info, void *user_data)
{
    bcm_ip6_t net = info->l3a_ip6_net;
    bcm_ip6_t mask = info->l3a_ip6_mask;
    int vrf = info->l3a_vrf;
    int intf = info->l3a_intf;
    int flags = info->l3a_flags;

    lr_seen++;
    printf("v6 %3d vrf %d ${net} mask ${mask} intf %d flags 0x%x\n",
           index, vrf, intf, flags);
    return BCM_E_NONE;
}

int lr_main()
{
    int unit = 0;
    int rv;
    int limit = 20;

    lr_seen = 0;
    rv = bcm_l3_route_traverse(unit, 0, 0, limit - 1, lr_v4_cb, NULL);
    printf("IPv4: rv %d (%s), %d shown (limit %d)\n", rv, bcm_errmsg(rv), lr_seen, limit);

    lr_seen = 0;
    rv = bcm_l3_route_traverse(unit, BCM_L3_IP6, 0, limit - 1, lr_v6_cb, NULL);
    printf("IPv6: rv %d (%s), %d shown (limit %d)\n", rv, bcm_errmsg(rv), lr_seen, limit);
    return 0;
}

lr_main();
printf("DONE l3_routes\n");

Hardware-validated

drivshell> cint /root/l3_routes.c
v4 10240 vrf 0 198.51.100.0 mask 255.255.255.0 intf 132807 flags 0x0
v4 12288 vrf 0 0.0.0.0 mask 0.0.0.0 intf 132806 flags 0x100000
IPv4: rv 0 (Ok), 2 shown (limit 20)
v6 13312 vrf 0 fe80:0000:0000:0000:0000:0000:0000:0000 mask ffc0:0000:0000:0000:0000:0000:0000:0000 intf 132807 flags 0x20000
v6 14336 vrf 0 0000:0000:0000:0000:0000:0000:0000:0000 mask 0000:0000:0000:0000:0000:0000:0000:0000 intf 132806 flags 0x120000
IPv6: rv 0 (Ok), 2 shown (limit 20)
DONE l3_routes

Egress objects

Lists L3 egress objects (next hops) with their MAC address, VLAN and port. The numbers match the INTF column of l3 egress show.

l3_egress.c
/*
 * l3_egress.c - list L3 egress objects (next hops) with
 * bcm_l3_egress_traverse().  Prints the first 50.  Read-only.
 * Run:  cint /root/l3_egress.c
 */
cint_reset();

int le_count = 0;
int le_limit = 50;

int le_cb(int unit, bcm_if_t intf, bcm_l3_egress_t *info, void *user_data)
{
    int vlan = info->vlan;

    le_count++;
    if (le_count > le_limit) {
        return BCM_E_NONE;
    }
    printf("egress %d: mac %02x:%02x:%02x:%02x:%02x:%02x vlan %d port %d module %d trunk %d intf %d flags 0x%x\n",
           intf,
           info->mac_addr[0], info->mac_addr[1], info->mac_addr[2],
           info->mac_addr[3], info->mac_addr[4], info->mac_addr[5],
           vlan, info->port, info->module, info->trunk, info->intf,
           info->flags);
    return BCM_E_NONE;
}

int le_main()
{
    int unit = 0;
    int rv;

    le_count = 0;
    rv = bcm_l3_egress_traverse(unit, le_cb, NULL);
    printf("rv %d (%s), %d egress objects\n", rv, bcm_errmsg(rv), le_count);
    return 0;
}

le_main();
printf("DONE l3_egress\n");

Hardware-validated

drivshell> cint /root/l3_egress.c
egress 132768: mac 00:00:00:00:00:01 vlan 1 port 0 module 0 trunk 0 intf 8192 flags 0xa00
egress 132769: mac 00:00:00:00:00:01 vlan 1 port 0 module 0 trunk 0 intf 8192 flags 0x200
egress 132770: mac 00:00:00:00:00:00 vlan 0 port 12 module 0 trunk -1 intf -1 flags 0x0
egress 132771: mac ff:ff:ff:ff:ff:ff vlan 0 port 12 module 0 trunk 0 intf 8195 flags 0x800
egress 132806: mac e0:39:d7:88:3b:00 vlan 1 port 0 module 0 trunk -1 intf 8194 flags 0x100000
egress 132807: mac e0:39:d7:88:3b:00 vlan 0 port 0 module 0 trunk -1 intf 16383 flags 0xb001000
rv 0 (Ok), 6 egress objects
DONE l3_egress

L2 table

Counts the MAC table and prints the first 30 entries. Compare l2 show.

l2_table.c
/*
 * l2_table.c - count the L2 (MAC) table and print the first 30 entries
 * with bcm_l2_traverse().  Read-only.  Run:  cint /root/l2_table.c
 */
cint_reset();

int lt2_count = 0;
int lt2_static = 0;
int lt2_limit = 30;

int lt2_cb(int unit, bcm_l2_addr_t *info, void *user_data)
{
    int vid = info->vid;

    lt2_count++;
    if (info->flags & BCM_L2_STATIC) {
        lt2_static++;
    }
    if (lt2_count > lt2_limit) {
        return BCM_E_NONE;
    }
    printf("%02x:%02x:%02x:%02x:%02x:%02x vlan %4d port %3d modid %d tgid %d flags 0x%x\n",
           info->mac[0], info->mac[1], info->mac[2],
           info->mac[3], info->mac[4], info->mac[5],
           vid, info->port, info->modid, info->tgid, info->flags);
    return BCM_E_NONE;
}

int lt2_main()
{
    int unit = 0;
    int rv;

    lt2_count = 0;
    lt2_static = 0;
    rv = bcm_l2_traverse(unit, lt2_cb, NULL);
    printf("rv %d (%s), %d entries (%d static)\n", rv, bcm_errmsg(rv), lt2_count, lt2_static);
    return 0;
}

lt2_main();
printf("DONE l2_table\n");

Hardware-validated

drivshell> cint /root/l2_table.c
e0:39:d7:88:3b:00 vlan    1 port   0 modid 0 tgid 0 flags 0x20
rv 0 (Ok), 1 entries (1 static)
DONE l2_table

VLANs

Lists every VLAN with its member and untagged ports. bcm_vlan_list allocates the list; the program frees it with bcm_vlan_list_destroy.

vlans.c
/*
 * vlans.c - list VLANs with their member and untagged ports using
 * bcm_vlan_list().  Read-only; frees the list it receives.
 * Run:  cint /root/vlans.c
 */
cint_reset();

int vl_main()
{
    int unit = 0;
    int rv;
    int i;
    int count = 0;
    int vid;
    bcm_vlan_t dflt;
    bcm_vlan_data_t *list = NULL;
    bcm_pbmp_t pbm;
    bcm_pbmp_t ubm;

    rv = bcm_vlan_default_get(unit, &dflt);
    vid = dflt;
    printf("default VLAN %d (rv %d)\n", vid, rv);

    rv = bcm_vlan_list(unit, &list, &count);
    if (rv != BCM_E_NONE) {
        printf("bcm_vlan_list failed: %s\n", bcm_errmsg(rv));
        return rv;
    }
    for (i = 0; i < count; i++) {
        vid = list[i].vlan_tag;
        pbm = list[i].port_bitmap;
        ubm = list[i].ut_port_bitmap;
        printf("vlan %4d ports ${pbm} untagged ${ubm}\n", vid);
    }
    printf("%d VLANs\n", count);
    bcm_vlan_list_destroy(unit, list, count);
    return 0;
}

vl_main();
printf("DONE vlans\n");

Hardware-validated

drivshell> cint /root/vlans.c
default VLAN 1 (rv 0)
vlan    1 ports { } untagged { }
vlan  902 ports { 12 } untagged { 12 }
vlan 3999 ports { } untagged { }
vlan 4095 ports { } untagged { }
4 VLANs
DONE vlans

KNET interfaces

Lists the KNET network interfaces, the Linux network devices through which SONiC sends and receives packets on each port, with the SDK port each is bound to. See KNET and the CPU port.

knet_netifs.c
/*
 * knet_netifs.c - list KNET network interfaces (the kernel netdevs that
 * SONiC uses for its EthernetN ports) and the SDK port each is bound to.
 * Read-only.  Run:  cint /root/knet_netifs.c
 */
cint_reset();

int kn_count = 0;

int kn_cb(int unit, bcm_knet_netif_t *netif, void *user_data)
{
    int vlan = netif->vlan;

    kn_count++;
    printf("netif %3d %-16s type %d port %3d vlan %4d flags 0x%x\n",
           netif->id, netif->name, netif->type, netif->port, vlan,
           netif->flags);
    return BCM_E_NONE;
}

int kn_main()
{
    int unit = 0;
    int rv;

    kn_count = 0;
    rv = bcm_knet_netif_traverse(unit, kn_cb, NULL);
    printf("rv %d (%s), %d netifs\n", rv, bcm_errmsg(rv), kn_count);
    return 0;
}

kn_main();
printf("DONE knet_netifs\n");

Hardware-validated

drivshell> cint /root/knet_netifs.c
netif   1 Ethernet0        type 2 port   1 vlan    0 flags 0x4
netif   2 Ethernet4        type 2 port   5 vlan    0 flags 0x4
netif   3 Ethernet8        type 2 port   9 vlan    0 flags 0x4
netif   4 Ethernet9        type 2 port  10 vlan    0 flags 0x4
netif   5 Ethernet10       type 2 port  11 vlan    0 flags 0x4
netif   6 Ethernet11       type 2 port  12 vlan    0 flags 0x4
netif   7 Ethernet12       type 2 port  13 vlan    0 flags 0x4
netif   8 Ethernet16       type 2 port  17 vlan    0 flags 0x4
netif   9 Ethernet20       type 2 port  21 vlan    0 flags 0x4
netif  10 Ethernet24       type 2 port  25 vlan    0 flags 0x4
netif  11 Ethernet28       type 2 port  29 vlan    0 flags 0x4
netif  12 Ethernet32       type 2 port  33 vlan    0 flags 0x4
netif  13 Ethernet36       type 2 port  37 vlan    0 flags 0x4
netif  14 Ethernet40       type 2 port  41 vlan    0 flags 0x4
netif  15 Ethernet44       type 2 port  45 vlan    0 flags 0x4
netif  16 Ethernet48       type 2 port  49 vlan    0 flags 0x4
netif  17 Ethernet52       type 2 port  53 vlan    0 flags 0x4
netif  18 Ethernet56       type 2 port  57 vlan    0 flags 0x4
netif  19 Ethernet60       type 2 port  61 vlan    0 flags 0x4
netif  20 Ethernet64       type 2 port  67 vlan    0 flags 0x4
netif  21 Ethernet68       type 2 port  71 vlan    0 flags 0x4
netif  22 Ethernet72       type 2 port  75 vlan    0 flags 0x4
netif  23 Ethernet76       type 2 port  79 vlan    0 flags 0x4
netif  24 Ethernet80       type 2 port  83 vlan    0 flags 0x4
netif  25 Ethernet84       type 2 port  87 vlan    0 flags 0x4
netif  26 Ethernet88       type 2 port  91 vlan    0 flags 0x4
netif  27 Ethernet92       type 2 port  95 vlan    0 flags 0x4
netif  28 Ethernet96       type 2 port  99 vlan    0 flags 0x4
netif  29 Ethernet100      type 2 port 103 vlan    0 flags 0x4
netif  30 Ethernet104      type 2 port 107 vlan    0 flags 0x4
netif  31 Ethernet108      type 2 port 111 vlan    0 flags 0x4
netif  32 Ethernet112      type 2 port 115 vlan    0 flags 0x4
netif  33 Ethernet116      type 2 port 119 vlan    0 flags 0x4
netif  34 Ethernet120      type 2 port 123 vlan    0 flags 0x4
netif  35 Ethernet124      type 2 port 127 vlan    0 flags 0x4
netif  36 Ethernet128      type 2 port  66 vlan    0 flags 0x4
rv 0 (Ok), 36 netifs
DONE knet_netifs

Field-processor groups

Lists the field-processor groups (SONiC ACL tables and the SAI’s own trap rules are implemented as field-processor groups), how many entries each has, and the priority of up to 16 entries per group. fp show prints the full contents.

field_groups.c
/*
 * field_groups.c - list field-processor (ACL) groups, their usage and the
 * priority of their first entries.  Read-only.
 * Run:  cint /root/field_groups.c
 */
cint_reset();

int fg_groups = 0;

int fg_cb(int unit, bcm_field_group_t group, void *user_data)
{
    bcm_field_group_status_t st;
    bcm_field_entry_t entries[16];
    int n = 0;
    int i;
    int prio;
    int rv;

    fg_groups++;
    rv = bcm_field_group_status_get(unit, group, &st);
    if (rv != BCM_E_NONE) {
        printf("group %d: status error %s\n", group, bcm_errmsg(rv));
        return BCM_E_NONE;
    }
    printf("group %d: %d entries, %d free of %d, prio %d..%d, %d counters\n",
           group, st.entry_count, st.entries_free, st.entries_total,
           st.prio_min, st.prio_max, st.counter_count);
    rv = bcm_field_entry_multi_get(unit, group, 16, entries, &n);
    for (i = 0; rv == BCM_E_NONE && i < n; i++) {
        prio = 0;
        bcm_field_entry_prio_get(unit, entries[i], &prio);
        printf("    entry %d prio %d\n", entries[i], prio);
    }
    return BCM_E_NONE;
}

int fg_main()
{
    int unit = 0;
    int rv;

    fg_groups = 0;
    rv = bcm_field_group_traverse(unit, fg_cb, NULL);
    printf("rv %d (%s), %d groups\n", rv, bcm_errmsg(rv), fg_groups);
    return 0;
}

fg_main();
printf("DONE field_groups\n");

Hardware-validated

drivshell> cint /root/field_groups.c
group 3: 0 entries, 1024 free of 1024, prio -2147483647..2147483647, 0 counters
group 2: 6 entries, 506 free of 512, prio 0..2147483647, 5 counters
    entry 3 prio 0
    entry 4 prio 2147483647
    entry 5 prio 2147483646
    entry 6 prio 2147483645
    entry 7 prio 2147483644
    entry 8 prio 2147483643
group 1: 29 entries, 3043 free of 3072, prio 0..2147483647, 25 counters
    entry 1 prio 0
    entry 2 prio 0
    entry 9 prio 1
    entry 10 prio 1
    entry 11 prio 1
    entry 12 prio 2
    entry 13 prio 1
    entry 14 prio 4
    entry 15 prio 4
    entry 16 prio 4
    entry 17 prio 4
    entry 18 prio 4
    entry 19 prio 4
    entry 20 prio 4
    entry 21 prio 4
    entry 22 prio 4
rv 0 (Ok), 3 groups
DONE field_groups

Enum values and switch controls

Shows how to get the number behind an enum name in this build, print an enum by name, and read a switch control.

enum_values.c
/*
 * enum_values.c - resolve SDK enum names to numbers in this build and read
 * one switch control.  Read-only.  Run:  cint /root/enum_values.c
 */
cint_reset();

int ev_main()
{
    int unit = 0;
    int rv;
    int value;
    int number;
    bcm_switch_control_t ctl;
    bcm_stat_val_t stat;

    ctl = bcmSwitchL3EgressMode;
    number = ctl;
    printf("bcmSwitchL3EgressMode = %d\n", number);
    print ctl;

    stat = snmpIfHCInOctets;
    number = stat;
    printf("snmpIfHCInOctets = %d (${stat})\n", number);

    value = -1;
    rv = bcm_switch_control_get(unit, bcmSwitchL3EgressMode, &value);
    printf("bcm_switch_control_get(L3EgressMode): rv %d (%s), value %d\n",
           rv, bcm_errmsg(rv), value);
    return 0;
}

ev_main();
printf("DONE enum_values\n");

Hardware-validated

drivshell> cint /root/enum_values.c
bcmSwitchL3EgressMode = 230
bcm_switch_control_t ctl = bcmSwitchL3EgressMode (230)
snmpIfHCInOctets = 58 (snmpIfHCInOctets)
bcm_switch_control_get(L3EgressMode): rv 0 (Ok), value 1
DONE enum_values

Arguments

Prints the arguments given after the file name.

args.c
/*
 * args.c - show the arguments passed after the file name.
 * Read-only.  Run:  cint /root/args.c one two 3
 */
cint_reset();

int args_show()
{
    int i;

    printf("ARGC = %d\n", ARGC);
    for (i = 0; i < ARGC; i++) {
        printf("ARGV[%d] = \"%s\"\n", i, ARGV[i]);
    }
    return 0;
}

args_show();
printf("DONE args\n");

Hardware-validated

drivshell> cint /root/args.c one two 3
ARGC = 3
ARGV[0] = "one"
ARGV[1] = "two"
ARGV[2] = "3"
DONE args

Diag commands from Cint

Runs ps through bshell and prints the result codes, including the code for an unknown command.

bshell_ps.c
/*
 * bshell_ps.c - run a diag shell command from Cint with bshell().
 * Read-only.  Run:  cint /root/bshell_ps.c
 */
cint_reset();

int bp_main()
{
    int unit = 0;
    int rv;

    rv = bshell(unit, "ps");
    printf("bshell(ps) returned %d\n", rv);
    rv = bshell(unit, "nosuchcommand");
    printf("bshell(nosuchcommand) returned %d\n", rv);
    return 0;
}

bp_main();
printf("DONE bshell_ps\n");

Hardware-validated

drivshell> cint /root/bshell_ps.c
                 ena/        speed/ link auto    STP                  lrn  inter   max   cut   loop
           port  link  Lns   duplex scan neg?   state   pause  discrd ops   face frame  thru?  back   encap
       ce0(  1)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce1(  5)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       xe0(  9)  up     1   10G  FD   SW  No   Forward         Untag    F    XFI  9122    No          IEEE
       xe1( 10)  up     1   10G  FD   SW  No   Forward         Untag    F    XFI  9122    No          IEEE
       xe2( 11)  up     1   10G  FD   SW  No   Forward         Untag    F    XFI  9122    No          IEEE
       xe3( 12)  up     1   10G  FD   SW  No   Forward          None    F    XFI  9122    No          IEEE
       ce2( 13)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce3( 17)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce4( 21)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce5( 25)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce6( 29)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce7( 33)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce8( 37)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       ce9( 41)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce10( 45)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce11( 49)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce12( 53)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce13( 57)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce14( 61)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
       xe4( 66)  !ena   1   10G  FD   SW  No   Forward         Untag    F    XFI  9122    No          IEEE
      ce15( 67)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce16( 71)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce17( 75)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce18( 79)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce19( 83)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce20( 87)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce21( 91)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
      ce22( 95)  !ena   4  100G  FD   SW  No   Forward         Untag    F    CR4  9122    No          IEEE
...