• qemu侧 网络包发送调试记录(二)


    断点记录

    (gdb) b e1000_class_init
    Breakpoint 2 at 0x555555a0b55f: file ../hw/net/e1000.c, line 1775.
    (gdb) b net_param_nic
    Breakpoint 3 at 0x555555914ee1: file ../net/net.c, line 1493.
    (gdb) b pci_e1000_realize
    Breakpoint 4 at 0x555555a0b33a: file ../hw/net/e1000.c, line 1705.
    (gdb) b pc_nic_init 
    Breakpoint 5 at 0x555555b6090a: file ../hw/i386/pc.c, line 1142.
    
    // 内存输出
    (gdb) x /6xb ni->macaddr.a
    
    // 通过 数组的方法 输出多个值
    (gdb) p {s->read_poll ,s->write_poll ,s->using_vnet_hdr ,s->has_ufo ,s->enabled}
    $22 = {true, false, false, true, true}
    (gdb) p *s
    value of type `TAPState' requires 71216 bytes, which is more than max-value-size
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    网络后端初始化

    net_param_nic 函数
    // 在执行net_param_nic 完成
    (gdb) p *ni
    $6 = {macaddr = {a = "RT\230vT2"}, model = 0x555556aa6540 "e1000", name = 0x0, 
      devaddr = 0x0, netdev = 0x555556cf99b0, used = 1, instantiated = 0, nvectors = 0}
    (gdb) x /6xb ni->macaddr.a
    0x5555569c5be0 <nd_table>:      0x52    0x54    0x98    0x76    0x54    0x32
    // netdev 就是下面的nc
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    net_client_init1
    (gdb) ptype Netdev
    type = struct Netdev {
        char *id;
        NetClientDriver type;
        union {
            NetLegacyNicOptions nic;
            NetdevUserOptions user;
            NetdevTapOptions tap;
            NetdevL2TPv3Options l2tpv3;
            NetdevSocketOptions socket;
            NetdevVdeOptions vde;
            NetdevBridgeOptions bridge;
            NetdevHubPortOptions hubport;
            NetdevNetmapOptions netmap;
            NetdevVhostUserOptions vhost_user;
            NetdevVhostVDPAOptions vhost_vdpa;
        } u;
    }
    
    (gdb) ptype NetClientDriver
    type = enum NetClientDriver {NET_CLIENT_DRIVER_NONE, NET_CLIENT_DRIVER_NIC, 
        NET_CLIENT_DRIVER_USER, NET_CLIENT_DRIVER_TAP, NET_CLIENT_DRIVER_L2TPV3, 
        NET_CLIENT_DRIVER_SOCKET, NET_CLIENT_DRIVER_VDE, NET_CLIENT_DRIVER_BRIDGE, 
        NET_CLIENT_DRIVER_HUBPORT, NET_CLIENT_DRIVER_NETMAP, 
        NET_CLIENT_DRIVER_VHOST_USER, NET_CLIENT_DRIVER_VHOST_VDPA, 
        NET_CLIENT_DRIVER__MAX}
      
    (gdb) ptype  NetdevTapOptions
    type = struct NetdevTapOptions {
        _Bool has_ifname;
        char *ifname;
        _Bool has_fd;
        char *fd;
        _Bool has_fds;
        char *fds;
        _Bool has_script;
        char *script;
        _Bool has_downscript;
        char *downscript;
        _Bool has_br;
        char *br;
        _Bool has_helper;
        char *helper;
        _Bool has_sndbuf;
        uint64_t sndbuf;
        _Bool has_vnet_hdr;
        _Bool vnet_hdr;
        _Bool has_vhost;
        _Bool vhost;
        _Bool has_vhostfd;
        char *vhostfd;
        _Bool has_vhostfds;
        char *vhostfds;
        _Bool has_vhostforce;
        _Bool vhostforce;
        _Bool has_queues;
        uint32_t queues;
        _Bool has_poll_us;
        uint32_t poll_us;
    }
    
    (gdb) p *netdev
    $8 = {id = 0x555556cdc950 "plr4", type = NET_CLIENT_DRIVER_TAP, u = { tap = {
          has_ifname = true, ifname = 0x555556aa73a0 "tap1", has_fd = false, fd = 0x0, 
          has_fds = false, fds = 0x0, has_script = true, script = 0x555556ce4cb0 "no", 
          has_downscript = true, downscript = 0x555556ce6ef0 "no", has_br = false, 
          br = 0x0, has_helper = false, helper = 0x0, has_sndbuf = false, sndbuf = 0, 
          has_vnet_hdr = false, vnet_hdr = false, has_vhost = false, vhost = false, 
          has_vhostfd = false, vhostfd = 0x0, has_vhostfds = false, vhostfds = 0x0, 
          has_vhostforce = false, vhostforce = false, has_queues = false, queues = 0, 
          has_poll_us = false, poll_us = 0}, }
    
    gdb) n
    1064        if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) {
    (gdb) s
    net_init_tap (netdev=0x0, name=0x7fffffffe2e0 "\020", peer=0x555555865940 <_start>, 
        errp=0x7fffffffdde0) at ../net/tap.c:796
    796     {
    
    (gdb) n
    1074            nc = qemu_find_netdev(netdev->id);
    (gdb) n
    1075            assert(nc);
    (gdb) p *nc
    $28 = {info = 0x5555568afb80 <net_tap_info>, link_down = 0, next = {}}, 
      peer = 0x0, incoming_queue = 0x555556aa6900, model =  "tap", name =  "plr4", 
      info_str = "ifname=tap1,script=no,downscript=no",  
      receive_disabled = 0, destructor = 0x55555591208f <qemu_net_client_destructor>, 
      queue_index = 0, rxfilter_notify_enabled = 0, vring_enable = 0, vnet_hdr_len = 0, 
      is_netdev = false, do_not_pad = false, is_datapath = true, filters = {}} 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    net_init_tap
    // 直接执行末尾的else 分支
    (gdb) n
    966             g_autofree char *default_script = NULL;
    // 这里是在qemu 命令行里指定 tap 名称,并且在创建的时候指定归属哪个用户,所以不需要sudo 执行
    (gdb) n
    982                 pstrcpy(ifname, sizeof ifname, tap->ifname);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    net_init_tap_one
    // 进入函数后,查看传入的参数
    (gdb) f
    #0  net_init_tap_one (tap=0x555556ce7740, peer=0x0, model=0x5555561311ad "tap", 
        name=0x555556cdc950 "plr4", ifname=0x7fffffffde10 "tap1", 
        script=0x555556ce4cb0 "no", downscript=0x555556ce6ef0 "no", vhostfdname=0x0, 
        vnet_hdr=1, fd=12, errp=0x7fffffffddc8) at ../net/tap.c:680
    680         Error *err = NULL;
    
    (gdb) f
    #0  net_tap_fd_init (peer=0x0, model=0x5555561311ad "tap", 
        name=0x555556cdc950 "plr4", fd=12, vnet_hdr=1) at ../net/tap.c:395
    395         nc = qemu_new_net_client(&net_tap_info, peer, model, name);
    
    (gdb) f
    #0  qemu_new_net_client (info=0x5555568afb80 <net_tap_info>, peer=0x0, 
        model=0x5555561311ad "tap", name=0x555556cdc950 "plr4") at ../net/net.c:273
    273         assert(info->size >= sizeof(NetClientState));
    
    (gdb) n
    net_tap_fd_init (peer=0x0, model=0x5555561311ad "tap", name=0x555556cdc950 "plr4", 
        fd=12, vnet_hdr=1) at ../net/tap.c:397
    397         s = DO_UPCAST(TAPState, nc, nc);
    (gdb) p *nc
    $15 = {info = 0x5555568afb80 <net_tap_info>, link_down = 0, next = {}, 
      peer = 0x0, incoming_queue = 0x555556aa6900, model = 0x555556aa6940 "tap", 
      name = 0x555556aa68e0 "plr4", info_str = '\000' <repeats 255 times>, 
      receive_disabled = 0, destructor = 0x55555591208f <qemu_net_client_destructor>, 
      queue_index = 0, rxfilter_notify_enabled = 0, vring_enable = 0, vnet_hdr_len = 0, 
      is_netdev = false, do_not_pad = false, is_datapath = true, filters = {
        tqh_first = 0x0, tqh_circ = {tql_next = 0x0, tql_prev = 0x555556cf9b18}}}
    
    // 回到 net_init_tap_one
    (gdb) n
    684         tap_set_sndbuf(s->fd, tap, &err);
    (gdb) p *(s->nc.incoming_queue)
    $20 = {opaque = 0x555556cf99b0, nq_maxlen = 10000, nq_count = 0, 
      deliver = 0x555555913408 <qemu_deliver_packet_iov>, packets = {tqh_first = 0x0, 
        tqh_circ = {tql_next = 0x0, tql_prev = 0x555556aa6918}}, delivering = 0}
    (gdb) p &(s->nc)
    $21 = (NetClientState *) 0x555556cf99b0
    (gdb) p {s->read_poll ,s->write_poll ,s->using_vnet_hdr ,s->has_ufo ,s->enabled}
    $22 = {true, false, false, true, true}
    
    // 这个可能让刚开始传入的包长度多10
    (gdb) p s->host_vnet_hdr_len 
    $23 = 10
    (gdb) p s->vhost_net 
    $24 = (VHostNetState *) 0x0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    网络前端初始化

    pci_nic_init_nofail
    (gdb) p nb_nics 
    $32 = 1
    
    (gdb) f
    #0  pci_nic_init_nofail (nd=0x5555569c5be0 <nd_table>, rootbus=0x555556e44ba0, 
        default_model=0x555556aa6540 "e1000", default_devaddr=0x0) at ../hw/pci/pci.c:1945
    
    // 直接 设置一个新的断点跳过循环
    (gdb) n 
    1983            next = list->next;
    (gdb) b 1989
    
    (gdb) p *pci_nic_models 
    $35 = {pdata = 0x555557742020, len = 26}
    (gdb) p devaddr
    $39 = 0x0
    
    // 对设备初始化
    (gdb) n
    2034        pci_realize_and_unref(pci_dev, bus, &error_fatal);
    (gdb) n
    
    Thread 1 "qemu-system-x86" hit Breakpoint 4, pci_e1000_realize (pci_dev=0x55555774d110, errp=0x7fffffffda88) at ../hw/net/e1000.c:1705
    1705    {
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    前端网卡设备初始化

    pci_e1000_realize 函数

    (gdb) s
    DEVICE (obj=0x55555774d110) at /home/ostest/linux-test/qemu7/include/hw/qdev-core.h:17
    17      OBJECT_DECLARE_TYPE(DeviceState, DeviceClass, DEVICE)
    (gdb) s
    1707        E1000State *d = E1000(pci_dev);
    (gdb) s
    E1000 (obj=0x55555774d110) at ../hw/net/e1000.c:159
    159     DECLARE_OBJ_CHECKERS(E1000State, E1000BaseClass,E1000, TYPE_E1000_BASE)
    
    (gdb) p d->nic
    $49 = (NICState *) 0x0
    
    (gdb) p d->conf 
    $50 = {macaddr = {a = "RT\230vT2"}, peers = {ncs = {0x555556cf99b0, 
          0x0 <repeats 1023 times>}, queues = 1}, bootindex = -1}
    
    (gdb) p d->conf->peers->ncs[0]
    $52 = (NetClientState *) 0x555556cf99b0
    (gdb) p *d->conf->peers->ncs[0]
    $53 = {info = 0x5555568afb80 <net_tap_info>, link_down = 0, next = {}, 
      peer = 0x0, incoming_queue = 0x555556aa6900, model = 0x555556aa6940 "tap", 
      name = 0x555556aa68e0 "plr4", }
    
    (gdb) n
    1740        d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
    (gdb) p *d->nic
    $55 = {ncs = 0x555557740570, conf = 0x55555774db18, opaque = 0x55555774d110, 
      peer_deleted = false}
     (gdb) p *d->nic->ncs 
    $57 = {info = 0x5555568d0520 <net_e1000_info>, link_down = 0, next = {tqe_next = 0x0, 
        tqe_circ = {tql_next = 0x0, tql_prev = 0x555556cf99c0}}, peer = 0x555556cf99b0, 
      incoming_queue = 0x5555577406f0, model = 0x555557740410 "e1000", 
      name = 0x555557740430 "e1000.0", 
      info_str = "model=e1000,macaddr=52:54:98:76:54:32",, }
     (gdb) p *d->nic->conf 
    $58 = {macaddr = {a = "RT\230vT2"}, peers = {ncs = {0x555556cf99b0, 
          0x0 <repeats 1023 times>}, queues = 1}, bootindex = -1}
    
    (gdb) p *d->nic->ncs->peer
    $59 = {info = 0x5555568afb80 <net_tap_info>, link_down = 0, next = {}, peer = 0x555557740570, }
    (gdb) p d
    $60 = (E1000State *) 0x55555774d110
    
    (gdb) p {d->autoneg_timer,d->mit_timer,d->flush_queue_timer}
    $63 = {0x555557740730, 0x555557740770, 0x5555577407b0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    Vue3 快速入门及巩固基础
    SpringBoot - SpringBoot配置说明
    Go语言 接口与类型
    linux笔记(8):东山哪吒D1H移植lvgl(HDMI输出)
    ROS下控制无人机任任意方向下往机头方向飞行
    RecursionError: maximum recursion depth exceeded while calling a Python object
    java计算机毕业设计桂林餐饮服务平台源码+mysql数据库+系统+lw文档+部署
    OpenGLES系列demo之(二):纹理映射
    C++数据结构 -- AVL树
  • 原文地址:https://blog.csdn.net/qq_41146650/article/details/127427315