比起Solaris的mdb/kmdb调试功能,Linux下的crash真是弱爆了。首先没有管道功能,其次不能在内核中设置断点。
不过总比没有强。添加了一些功能方便调试我们的网卡驱动程序。
diff--git a/defs.h b/defs.h
index edccdc7..4cb8276 100644
--- a/defs.h
+++ b/defs.h
@@ -4661,6 +4661,7 @@ void cmd_fuser(void); /* filesys.c */
void cmd_dev(void); /* dev.c */
void cmd_gdb(void); /* gdb_interface.c */
void cmd_net(void); /* net.c */
+void cmd_flow(void); /* net.c*/
void cmd_extend(void); /* extensions.c */
#if defined(S390) ||defined(S390X)
void cmd_s390dbf(void);
diff --git a/global_data.c b/global_data.c
index 998aaae..5e291f7 100644
--- a/global_data.c
+++ b/global_data.c
@@ -94,6 +94,7 @@ struct command_table_entry linux_command_table[] = {
{"mod", cmd_mod, help_mod, 0},
{"mount", cmd_mount, help_mount, 0},
{"net", cmd_net, help_net, REFRESH_TASK_TABLE},
+ {"flow", cmd_flow, help_net, REFRESH_TASK_TABLE},
{"p", cmd_p, help_p, 0},
{"ps", cmd_ps, help_ps, REFRESH_TASK_TABLE},
{"pte", cmd_pte, help_pte, 0},
diff --git a/net.c b/net.c
index bb86963..df4f48f 100644
--- a/net.c
+++ b/net.c
@@ -20,6 +20,7 @@
#include <netdb.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
+#include <stdlib.h>
/*
* Cache values we need that can change based on OS version, or anyother
@@ -313,7 +314,8 @@ net_init(void)
* The net command...
*/
-#define NETOPTS "N:asSR:xdn"
+#define NETOPTS "N:asSR:xdnl:"
+#define FLOWOPTS "a:b:"
#define s_FLAG FOREACH_s_FLAG
#define S_FLAG FOREACH_S_FLAG
#define x_FLAG FOREACH_x_FLAG
@@ -329,6 +331,8 @@ net_init(void)
#define NET_REFERENCE_CHECK(X) (X)
#define NET_REFERENCE_FOUND(X) ((X) && ((X)->cmdflags &NET_REF_FOUND))
+char *link_name;
+
void
cmd_net(void)
{
@@ -359,6 +363,10 @@ cmd_net(void)
}
break;
+ case 'l':
+ link_name = optarg;
+ break;
+
case'a':
dump_arp();
aflag++;
@@ -425,7 +433,7 @@ cmd_net(void)
if(sflag & (s_FLAG|S_FLAG))
dump_sockets(sflag,ref);
else{
- if ((argcnt == 1) ||nflag)
+ if ((argcnt == 1) || nflag|| link_name)
show_net_devices(task);
elseif (!aflag)
cmd_usage(pc->curcmd,SYNOPSIS);
@@ -529,6 +537,39 @@ show_net_devices_v2(ulong task)
FREEBUF(net_device_buf);
}
+ulong read_pointer(char *name)
+{
+ ulong p, buf[1];
+ p = symbol_value(name);
+
+ readmem(p, KVADDR, buf, sizeof(ulong),name, FAULT_ON_ERROR);
+
+ return buf[0];
+}
+
+ulong read_pointer2(ulong addr, char *type, char *member)
+{
+ int offset;
+ char *buf;
+ ulong val;
+
+ offset = MEMBER_OFFSET(type,member);
+ buf =malloc(offset+sizeof(ulong));
+
+ if (buf == NULL)
+ return 0;
+
+ readmem(addr, KVADDR, buf, offset +sizeof(ulong), "addr", FAULT_ON_ERROR);
+
+ val = *((ulong *)&buf[offset]);
+ free(buf);
+
+ return val;
+}
+
+ulong mlx5e_priv;
+ulong table_test;
+
static void
show_net_devices_v3(ulong task)
{
@@ -581,10 +622,40 @@ show_net_devices_v3(ulong task)
get_device_name(ld->list_ptr[i],buf);
fprintf(fp,"%-6s ", buf);
+ if (link_name)
+ if (strcmp(buf,link_name) == 0)
+ mlx5e_priv =ld->list_ptr[i] + SIZE(net_device);
+
get_device_address(ld->list_ptr[i],buf);
fprintf(fp,"%s\n", buf);
}
-
+
+ if (link_name) {
+ fprintf(fp,"\n%s:\n", link_name);
+ fprintf(fp,"mlx5e_priv %llx\n",mlx5e_priv);
+
+ ulong fs = mlx5e_priv +MEMBER_OFFSET("mlx5e_priv", "fs");
+ fprintf(fp,"mlx5e_flow_steering %llx\n",fs);
+
+ ulong ppriv = read_pointer2(mlx5e_priv,"mlx5e_priv", "ppriv");
+ fprintf(fp,"mlx5_eswitch_rep %llx\n",ppriv);
+
+ ulong mdev = read_pointer2(mlx5e_priv,"mlx5e_priv", "mdev");
+ fprintf(fp,"mlx5_core_dev %llx\n",mdev);
+
+ ulong mlx5_priv = mdev +MEMBER_OFFSET("mlx5_core_dev", "priv");
+ fprintf(fp,"mlx5_priv %llx\n",mlx5_priv);
+
+ ulong esw = read_pointer2(mlx5_priv,"mlx5_priv", "eswitch");
+ fprintf(fp,"mlx5_eswitch %llx\n",esw);
+
+ ulong fdb_table = esw +MEMBER_OFFSET("mlx5_eswitch", "fdb_table");
+ fprintf(fp,"mlx5_eswitch_fdb %llx\n",fdb_table);
+ table_test =read_pointer2(fdb_table, "mlx5_eswitch_fdb", "fdb");
+ }
+
+ link_name = NULL;
+
FREEBUF(ld->list_ptr);
FREEBUF(net_device_buf);
}
@@ -1663,3 +1734,112 @@ sym_socket_dump(ulong file,
returnTRUE;
}
+
+void
+cmd_flow(void)
+{
+ int c;
+ char *addr;
+ char *ptr;
+ ulong a;
+ struct list_data group,*ld_group;
+ struct list_data fte,*ld_fte;
+ struct list_data rule,*ld_rule;
+ int n1, n2, n3, i1, i2, i3;
+ int show;
+
+ while ((c = getopt(argcnt, args,FLOWOPTS)) != EOF) {
+ switch (c) {
+ case 'a':
+ show = 1;
+ addr = optarg;
+ break;
+ case 'b':
+ show = 2;
+ addr = optarg;
+ break;
+ }
+ }
+
+ a = strtoul(addr, &ptr,16);
+/* a = table_test; */
+
+ fprintf(fp,"mlx5_flow_table %llx -x\n",a);
+
+ ld_group = &group;
+ BZERO(ld_group, sizeof(structlist_data));
+ ld_group->flags |=LIST_ALLOCATE;
+
+ ld_group->start =ld_group->end = a + MEMBER_OFFSET("fs_node","children");
+ ld_group->list_head_offset =0;
+
+ n1 = do_list(ld_group);
+
+ if (show == 1) {
+ for (i1 = 1; i1 < n1;++i1) {
+ ulong t1 =ld_group->list_ptr[i1];
+ fprintf(fp,"\tmlx5_flow_group.mask %llx -x\n", t1);
+
+ ld_fte = &fte;
+ BZERO(ld_fte,sizeof(struct list_data));
+ ld_fte->flags |=LIST_ALLOCATE;
+
+ ld_fte->start =ld_fte->end = t1 + MEMBER_OFFSET("fs_node","children");
+ ld_fte->list_head_offset= 0;
+
+ n2 =do_list(ld_fte);
+ for (i2 = 1; i2 <n2; ++i2) {
+ ulong t2 =ld_fte->list_ptr[i2];
+ fprintf(fp,"\t\tfs_fte.val %llx -x\n",t2);
+
+ ld_rule = &rule;
+ BZERO(ld_rule,sizeof(struct list_data));
+ ld_rule->flags|= LIST_ALLOCATE;
+
+ ld_rule->start= ld_rule->end = t2 + MEMBER_OFFSET("fs_node","children");
+ ld_rule->list_head_offset= 0;
+
+ n3 =do_list(ld_rule);
+
+ for (i3 = 1; i3< n3; ++i3) {
+ ulong t3= ld_rule->list_ptr[i3];
+ fprintf(fp,"\t\t\tmlx5_flow_rule.dest_attr %llx -x\n", t3);
+ }
+ }
+ }
+ } else if (show == 2) {
+ for (i1 = 1; i1 < n1;++i1) {
+ ulong t1 =ld_group->list_ptr[i1];
+ fprintf(fp,"\tlist -H %llx -s mlx5_flow_group.mask -x\n",ld_group->list_ptr[0]);
+
+ ld_fte = &fte;
+ BZERO(ld_fte,sizeof(struct list_data));
+ ld_fte->flags |=LIST_ALLOCATE;
+
+ ld_fte->start =ld_fte->end = t1 + MEMBER_OFFSET("fs_node","children");
+ ld_fte->list_head_offset= 0;
+
+ n2 =do_list(ld_fte);
+ for (i2 = 1; i2 <n2; ++i2) {
+ ulong t2 =ld_fte->list_ptr[i2];
+ fprintf(fp,"\t\tlist -H %llx -s fs_fte.val -x\n", ld_fte->list_ptr[0]);
+
+ ld_rule = &rule;
+ BZERO(ld_rule,sizeof(struct list_data));
+ ld_rule->flags|= LIST_ALLOCATE;
+
+ ld_rule->start= ld_rule->end = t2 + MEMBER_OFFSET("fs_node", "children");
+ ld_rule->list_head_offset= 0;
+
+ n3 =do_list(ld_rule);
+
+ ulong t3 =ld_rule->list_ptr[i3];
+ fprintf(fp,"\t\t\tlist -H %llx -s mlx5_flow_rule.dest_attr -x\n",ld_rule->list_ptr[0]);
+ }
+ }
+ }
+
+ FREEBUF(ld_group->list_ptr);
+ FREEBUF(ld_fte->list_ptr);
+ FREEBUF(ld_rule->list_ptr);
+}
crash> net -l p2p1
NET_DEVICE NAME IP ADDRESS(ES)
ffff880c66c79000 lo 127.0.0.1
ffff8806615fc000 em1 10.200.0.168
ffff880660c78000 em2
ffff88056200a000 virbr0 192.168.122.1
ffff880562978000 virbr0-nic
ffff88055e16d000 ovs-system
ffff880c016d0000 p4p1
ffff8805fcdd0000 p4p2
ffff88039aa30000 p2p1
ffff88039b430000 p2p2
ffff8803a2d20000 p7p1
ffff880c4fbf0000 p7p2
ffff8803a11f0000 p2p1_0
ffff8805af9a0000 p2p1_1
ffff880c60507000 br0
ffff880610d8c000 vnet0
ffff880c1779c000 vnet1
p2p1:
mlx5e_priv ffff88039aa308c0
mlx5e_flow_steering ffff88039aa32eb0
mlx5_eswitch_rep ffff88065f60fc00
mlx5_core_dev ffff8806325c0060
mlx5_priv ffff8806325f60d8
mlx5_eswitch ffff88055ed2a000
mlx5_eswitch_fdb ffff88055ed2a818
crash> mlx5_eswitch_fdb ffff88055ed2a818
struct mlx5_eswitch_fdb {
fdb = 0xffff880b4966fe00,
{
legacy = {
addr_grp = 0xffff8805d355a700,
allmulti_grp = 0xffff880666d44c00,
promisc_grp = 0xffff880666d41000
},
offloads = {
fdb = 0xffff8805d355a700,
send_to_vport_grp = 0xffff880666d44c00,
miss_grp = 0xffff880666d41000,
miss_rule = 0xffff88060e5face0,
vlan_push_pop_refcount = 0x4
}
}
}
crash> flow -a 0xffff880b4966fe00
mlx5_flow_table ffff880b4966fe00 -x
mlx5_flow_group.mask ffff880666d40800 -x
fs_fte.val,index ffff880666d41800 -x
mlx5_flow_rule.dest_attr ffff8805e28ffd40 -x
mlx5_flow_rule.dest_attr ffff8805e28ff8c0 -x
fs_fte.val,index ffff880614090000 -x
mlx5_flow_rule.dest_attr ffff88065fbd0d80 -x
mlx5_flow_rule.dest_attr ffff88065fbd0fc0 -x
mlx5_flow_group.mask ffff880614097000 -x
fs_fte.val,index ffff880614091c00 -x
mlx5_flow_rule.dest_attr ffff88065fbd15c0 -x
mlx5_flow_rule.dest_attr ffff88065fbd1b00 -x
fs_fte.val,index ffff8806666afc00 -x
mlx5_flow_rule.dest_attr ffff880c66c12cc0 -x
mlx5_flow_rule.dest_attr ffff880c66c12d80 -x
crash> flow -b 0xffff880b4966fe00
mlx5_flow_table ffff880b4966fe00 -x
list -H ffff880b4966fe10 -s mlx5_flow_group.mask -x
list -H ffff880666d40810 -s fs_fte.val,index -x
list -H ffff880666d41810 -s mlx5_flow_rule.dest_attr -x
list -H ffff880666d40810 -s fs_fte.val,index -x
list -H ffff880614090010 -s mlx5_flow_rule.dest_attr -x
list -H ffff880b4966fe10 -s mlx5_flow_group.mask -x
list -H ffff880614097010 -s fs_fte.val,index -x
list -H ffff880614091c10 -s mlx5_flow_rule.dest_attr -x
list -H ffff880614097010 -s fs_fte.val,index -x
list -H ffff8806666afc10 -s mlx5_flow_rule.dest_attr -x