LwIP協議棧(2):網路介面
阿新 • • 發佈:2019-01-27
在LwIP中,物理網路硬體介面結構儲存在一個全域性連結串列中,它們通過結構體中的 next 指標連線。
struct netif {
/// pointer to next in linked list */
struct netif *next;
/// IP address configuration in network byte order */
ip_addr_t ip_addr; //IP地址
ip_addr_t netmask; //子網掩碼
ip_addr_t gw; //閘道器地址
netif_input_fn input; //裝置驅動呼叫該函式傳遞一個包給TCP/IP協議棧
//IP模組呼叫該函式傳遞一個包給網絡卡,output 函式的第三個引數 ipaddr 是應該接收實際的鏈路層幀的主機的 IP 地址。
//它不必與 IP 資訊包的目的地址相同。特別地,當要傳送 IP 資訊包到一個並不在本地網路裡的主機上時,鏈路層幀會被髮送到網路裡的一個路由器上。
//在這種情況下給output函式的IP地址將是這個路由器的地址。
netif_output_fn output;
netif_linkoutput_fn linkoutput; //ARP模組呼叫該函式傳遞一個包給網絡卡
void *state; //由裝置驅動設定,指向裝置狀態資訊
#if LWIP_DHCP
/// the DHCP client state information for this netif */
struct dhcp *dhcp;
#endif // LWIP_DHCP */
#if LWIP_AUTOIP
/// the AutoIP client state information for this netif */
struct autoip *autoip;
#endif
#if LWIP_NETIF_HOSTNAME
// the hostname for this netif, NULL is a valid value */
char* hostname;
#endif // LWIP_NETIF_HOSTNAME */
u16_t mtu; //一次傳送的最大位元組數,乙太網一般為1500
u8_t hwaddr_len; //實體地址長度,一般是乙太網MAC地址長度,6位元組
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; //實體地址,一般是乙太網MAC地址
/// flags (see NETIF_FLAG_ above) */
u8_t flags; //使能標誌符,比如設定NETIF_FLAG_LINK_UP,接收到資料包才會向上傳
/// descriptive abbreviation */
char name[2]; //裝置驅動型別
/// number of this interface */
u8_t num;
// List of packets to be queued for ourselves. */
struct pbuf *loop_first; //環回,指向發給自己資料包的第一個pbuf
struct pbuf *loop_last; //環回,指向發給自己資料包的最後一個pbuf
};
/*
* Add a network interface to the list of lwIP netifs.
*
* @param netif a pre-allocated netif structure
* @param ipaddr IP address for the new netif
* @param netmask network mask for the new netif
* @param gw default gateway IP address for the new netif
* @param state opaque data passed to the new netif
* @param init callback function that initializes the interface
* @param input callback function that is called to pass
* ingress packets up in the protocol layer stack.
*
* @return netif, or NULL if failed.
*/
struct netif *
netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
{
static u8_t netifnum = 0;
// reset new interface configuration state */
ip_addr_set_zero(&netif->ip_addr);
ip_addr_set_zero(&netif->netmask);
ip_addr_set_zero(&netif->gw);
netif->flags = 0;
// remember netif specific state information data */
netif->state = state;
netif->num = netifnum++;
netif->input = input;
netif_set_addr(netif, ipaddr, netmask, gw);
// call user specified initialization function for netif */
if (init(netif) != ERR_OK) { //使用者自定義初始化函式
return NULL;
}
// add this netif to the list */
netif->next = netif_list;
netif_list = netif;
snmp_inc_iflist();
return netif;
}
//使用者自定義初始化函式
err_t ethernetif_init(struct netif *netif)
{
netif->name[0] = IFNAME0; //比如藍芽裝置(bluetooth)的網路介面可以是bt,隨便啦
netif->name[1] = IFNAME1;
netif->output = etharp_output; //IP模組傳送資料包函式
netif->linkoutput = low_level_output; // //ARP模組傳送資料包函式
low_level_init(netif); //底層硬體初始化函式
return ERR_OK;
}
static void low_level_init(struct netif *netif)
{
netif->hwaddr_len = ETHARP_HWADDR_LEN; //設定MAC地址長度
netif->hwaddr[0] = 'F'; //設定網絡卡MAC地址
netif->hwaddr[1] = 'O';
netif->hwaddr[2] = 'R';
netif->hwaddr[3] = 'E';
netif->hwaddr[4] = 'S';
netif->hwaddr[5] = 'T';
netif->mtu = 1500; //最大允許傳輸單元
//允許該網絡卡的廣播和ARP功能,並且該網絡卡允許有硬體鏈路連線
netif->flags = NETIF_FLAG_BROADCAST | \
NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
E1280_init(netif->hwaddr); //具體網絡卡初始化函式
}
/*
* Send an IP packet to be received on the same netif (loopif-like).
* The pbuf is simply copied and handed back to netif->input.
* In multithreaded mode, this is done directly since netif->input must put
* the packet on a queue.
* In callback mode, the packet is put on an internal queue and is fed to
* netif->input by netif_poll().
*
* @param netif the lwip network interface structure
* @param p the (IP) packet to 'send'
* @param ipaddr the ip address to send the packet to (not used)
* @return ERR_OK if the packet has been sent
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
*/
err_t
netif_loop_output(struct netif *netif, struct pbuf *p,
ip_addr_t *ipaddr)
{
struct pbuf *r;
err_t err;
struct pbuf *last;
SYS_ARCH_DECL_PROTECT(lev);
LWIP_UNUSED_ARG(ipaddr);
// Allocate a new pbuf */
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
if (r == NULL) {
return ERR_MEM;
}
// Copy the whole pbuf queue p into the single pbuf r */
if ((err = pbuf_copy(r, p)) != ERR_OK) { //拷貝要傳送的資料到r中
pbuf_free(r);
return err;
}
// Put the packet on a linked list which gets emptied through calling
netif_poll(). */
//可以呼叫netif_poll函式將當前loop連結串列上所有資料提交給IP層
// let last point to the last pbuf in chain r */
for (last = r; last->next != NULL; last = last->next);
SYS_ARCH_PROTECT(lev);
if(netif->loop_first != NULL) { //原來的loop中還有資料
netif->loop_last->next = r; //接到原來資料的後面
netif->loop_last = last;
} else {
netif->loop_first = r;
netif->loop_last = last;
}
SYS_ARCH_UNPROTECT(lev);
return ERR_OK;
}
/*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
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\n"));
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
/*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
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); //拷貝接收到的資料到一個新的pbuf
// 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:
// full packet send to tcpip_thread to process */
if (netif->input(p, netif)!=ERR_OK) //呼叫上層(IP/ARP)函式進行處理
{
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}