嵌入式技术论坛
直播中

ss

7年用户 8762经验值
擅长:电源/新能源 制造/封装 RF/无线
私信 关注
[问答]

RTT上移植的lwip为何不用单一进程维护eth设备呢

研究了一下RTT上移植的lwip
1、问题,为何不用单一进程维护eth设备?
既然采用了ipc来传递报文,为何不用单一进程维护eth设备呢?我看过一些wlan的驱动,设备主要都是有一个主进程维护(大致采用switch(msg_get(mbox)){case tx: case rx: case other:}这种结构),收包、发包、命令都是在这个进程中完成,状态变更的信息也是从这个进程发出;对设备的访问在时域上天然不会重入;进程功能上也划分的很清晰;想听听您移植中的一些想法。
2、建议,让lwip来处理arp是不是更好?
先上代码(从google仓库新获取),
rrt中的eth_input()
err_t eth_input(struct pbuf *p, struct netif *inp)
{
  struct eth_hdr *ethhdr;
  if(p != RT_NULL)
  {
#ifdef LINK_STATS
    LINK_STATS_INC(link.recv);
#endif /* LINK_STATS */
    ethhdr = p->payload;
    switch(htons(ethhdr->type))
    {
    case ETHTYPE_IP:
      etharp_ip_input(inp, p);
      pbuf_header(p, -14);
      tcpip_input(p, inp);
      break;
    case ETHTYPE_ARP:
      etharp_arp_input(inp, (struct eth_addr *)inp->hwaddr, p);
      break;
    default:
      pbuf_free(p);
      p = RT_NULL;
      break;
    }
  }
  return ERR_OK;
}
rtt移植的lwip接收数据包是由独立进程完成,在获取pbuf之后,调用eth_input()交付数据包;
eth_input()区分对待ARP和IP报文,采用不同方式处理;很明显,ARP的处理是在本地完成的,而且可能会涉及到发送报文的操作;
这种处理方式我觉得不妥,
首先,从功能、代码的划分隔离度角度上看,接收报文的线程牵扯到太多tcpip 的协议工作,不能体现进程功能的独立性;
其次,从功能上看,由于arp操作可能会涉及到发包,那么会看到有两个进程可以发包,两者同时存在,职能不独立,不美观。
建议,将arp的处理转移到tcpip主进程中来处理,官网下载的lwip130,其中:
来自于 Ethernetif.c
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;
  ethernetif = netif->state;
  /* move received packet into a new pbuf */
  p = low_level_input(netif);
  /* no packet could be read, silently ignore this */
  if (p == NULL) return;
  /* points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;
  switch (htons(ethhdr->type)) {
  /* IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:
#if PPPOE_SUPPORT
  /* PPPoE packet? */
  case ETHTYPE_PPPOEDISC:
  case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
    /* full packet send to tcpip_thread to process */
    if (netif->input(p, netif)!=ERR_OK)
     { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error
"));
       pbuf_free(p);
       p = NULL;
     }
    break;
  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
}
可以看到,不管是ip arp,底层接收到包后,直接转移到tcpip_thread()中了(主进程中有处理arp相关的部分)。

回帖(4)

ss

2022-3-18 09:35:37
1、多线程做收发的问题。
ETH Rx, Tx线程分离:有的时候还需要考虑到优先级的问题,如果Rx/Tx线程合二为一,那么整个过程将变为串行的流程,收发之间必定相互牵制(例如已经有一些报文堆积在线程上等待发送,而接收中断到达,这个时候收还是不收,很为难)。有的时候需要一方能够获得更大的吞吐能力,收发分离将是比较好的策略。(这个过程有的时候甚至会牵扯到tcp线程的优先级)所以现在的方式还是把它分离开来,同时对这三者的优先级都可以通过rtconfig.h进行配置。

2、确实,目前arp是由erx线程进行处理的。逻辑上,从tcp的视角来看,相对混乱些。但从驱动这个视角来看,驱动只需要考虑收发过程即可,而不用像lwip原版那样,驱动还要提供arp报文剥离的函数。这部分或许有更好的办法,还没来得及仔细考虑。

另外,这些做法没有完全的正确与错误,所以这个要因时势来看。欢迎提出更好的意见,特别是第二点上,是否有可能既能保持驱动的简单独立而又能够保持tcp线程的相对完整。
举报

ss

2022-3-18 09:35:46
lwip 1.3.0 的change log上,已经明确的说明了在tcpip_thread()中已经可以接受arp的报文了,而且现在代码里已经不在lwip主进程之外处理协议(arp)了。
举报

ss

2022-3-18 09:37:00
DHCP的困局

lwip中 tcpip_thread进程的启动问题,先上代码(rtt0.3.0 from svn):

sys_arch_init.c

void lwip_sys_init()

{

  struct ip_addr ipaddr, netmask, gw;

#if LWIP_DHCP

  rt_uint32_t mscnt = 0;

  IP4_ADDR(&gw, 0,0,0,0);

  IP4_ADDR(&ipaddr, 0,0,0,0);

  IP4_ADDR(&netmask, 0,0,0,0);

#else

  IP4_ADDR(&ipaddr, RT_LWIP_IPADDR0, RT_LWIP_IPADDR1, RT_LWIP_IPADDR2, RT_LWIP_IPADDR3);

  IP4_ADDR(&gw, RT_LWIP_GWADDR0, RT_LWIP_GWADDR1, RT_LWIP_GWADDR2, RT_LWIP_GWADDR3);

  IP4_ADDR(&netmask, RT_LWIP_MSKADDR0, RT_LWIP_MSKADDR1, RT_LWIP_MSKADDR2, RT_LWIP_MSKADDR3);

#endif

    tcpip_init(RT_NULL, RT_NULL);

  netif_set_addr(netif_default, &ipaddr, &netmask, &gw);

  netif_set_up(netif_default);

#if LWIP_DHCP

  /* use DHCP client */

  dhcp_start(netif_default);

    while (1) {

        rt_thread_delay(DHCP_FINE_TIMER_MSECS);

        dhcp_fine_tmr();

        mscnt += DHCP_FINE_TIMER_MSECS;

        if (mscnt >= DHCP_COARSE_TIMER_SECS*1000)

        {

            dhcp_coarse_tmr();

            mscnt = 0;

        }

    }

#endif

#if defined(RT_USING_FINSH) && (LWIP_STATS_DISPLAY)

    finsh_syscall_append("lwip_info", (syscall_func)stats_display);

#endif

}

上述代码是引导启动tcpip_thread主进程的关键代码,看代码的流程,如果打开了DHCH,后面的“finsh_syscall_append...”似乎就运转不成啦。这里,代码中支持DHCP的while循环是否应该放在某个进程的末尾,充当DHCP的维持呢?
举报

ss

2022-3-18 09:37:07
这段代码是有问题的,更新下代码,在版本r170的时候已经修正过这段代码。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分