STM 32 LwIPシングルNICバインド複数IPアドレス
12186 ワード
STM 32 LwIPシングルNICバインド複数IPアドレス
チップ:STM 32 F 107 VC
コンパイラ:KEIL 4
作者:SY
日付:2018-6-28 11:02:53
概要
物理ネットワークカードが1つしかない場合、ソフトウェアを介して複数の
IP
を仮想化し、時間分割通信することができる.LwIP
STM32F107VC
インプリメンテーション
まず、
LwIP
を移植し、単一のIP
で利用できることを保証する.次に仮想NICを追加します.
void LwIP_Init(void)
{
/* 1 */
IP4_ADDR(&ipaddr1, 192, 168, 0, 234);
IP4_ADDR(&netmask1, 255, 255, 255, 0);
IP4_ADDR(&gw1, 192, 168, 0, 1);
netif_add(&netif1, &ipaddr1, &netmask1, &gw1, NULL, ðernetif_init, ðernet_input);
netif_set_up(&netif1);
netif_set_default(&netif1);
/* 2 */
IP4_ADDR(&ipaddr2, 192, 168, 1, 234);
IP4_ADDR(&netmask2, 255, 255, 255, 0);
IP4_ADDR(&gw2, 192, 168, 1, 1);
netif_add(&netif2, &ipaddr2, &netmask2, &gw2, NULL, ðernetif_init, ðernet_input);
netif_set_up(&netif2);
/* UDP */
struct udp_pcb *UdpPcb;
/* Create a new UDP control block */
UdpPcb = udp_new();
/* Bind the upcb to any IP address and the UDP_PORT port*/
udp_bind(UdpPcb, IP_ADDR_ANY, UDP_CLIENT_PORT);
/* Set a receive callback for the upcb */
udp_recv(UdpPcb, udp_client_callback, NULL);
}
このように処理すると、次の問題が発生します.
IP
は、データを受け取ることができず、イーサネットデバッグアシスタントを使用してIP
にデータを送信してもパケットをつかむことができません.イーサネット通信プロトコルによれば、ローカルエリアネットワーク内のデータ送受信は、
MAC
アドレスで通信する必要があるため、まずARP
パケットを送信する必要があり、目的のIP
にプロトコルパケットを送信し、相手のMAC
を要求する必要がある.パッケージツールで調べたところ、やはり、パソコン側から送信されたARP
パケットは、デバイスから返信されなかった.したがって、
ARP
を修正する./*
*********************************************************************************************************
* Function Name : GetActiveNetif
* Description :
* Input : None
* Output : None
* Return : None
*********************************************************************************************************
*/
struct netif *GetActiveNetif(struct ip_addr *src_ip)
{
struct netif *curNetif = NULL;
if (ip_addr_cmp(src_ip, &netif1.ip_addr)) {
curNetif = &netif1;
} else if (ip_addr_cmp(src_ip, &netif2.ip_addr)) {
curNetif = &netif2;
}
return curNetif;
}
パケットの
IP
フィールドを解析し、現在の2
枚のNICの IP
フィールドと比較することで、パケットがどのNICに送信されたかを特定します.void
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
/* this interface is not configured? */
if (netif->ip_addr.addr == 0) {
for_us = 0;
} else {
/* ARP packet directed to us? */
struct netif *GetActiveNetif(struct ip_addr *src_ip);
struct netif *activeNetif = GetActiveNetif(&dipaddr);
if (activeNetif != NULL) {
for_us = 1;
netif = activeNetif;
}
}
/* ARP message directed to us? */
if (for_us) {
/* add IP address in ARP cache; assume requester wants to talk to us.
* can result in directly sending the queued packets for this host. */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
/* ARP message not directed to us? */
} else {
/* update the source IP address in the cache, if present */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
}
}
上記の修正により、上位機のパケットを受け取ることができます.
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void
low_level_init(struct netif *netif)
{
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP;
}
以上のヒントに従って、複数のネットワークがある場合は、
NETIF_FLAG_ETHARP
フィールドを削除する必要があります.OK
、上記の変更により、両方のIP
がパケットを受信することができる.まとめ
IPアドレスは異なるセグメントに構成する必要がある
IP
ルーティング規則を参照:/**
* Finds the appropriate network interface for a given IP address. It
* searches the list of network interfaces linearly. A match is found
* if the masked IP address of the network interface equals the masked
* IP address given to the function.
*
* @param dest the destination IP address for which to find the route
* @return the netif on which to send to reach dest
*/
struct netif *
ip_route(struct ip_addr *dest)
{
struct netif *netif;
/* iterate through netifs */
for(netif = netif_list; netif != NULL; netif = netif->next) {
/* network mask matches? */
if (netif_is_up(netif)) {
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
/* return netif on which to forward IP packet */
return netif;
}
}
}
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"
", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes();
return NULL;
}
/* no matching netif found, use default netif */
return netif_default;
}
2枚のNICの
IP
が同じセグメントにある場合、NICを巡るときに、最後に追加されたNICが優先されます.つまり、どのNICにパケットを送信しても、デバイスがデータを返信するときに、2枚目のNICからデータが返信されます.例えば、
IP (192, 168, 0, 234)
にパケットを送信し、データの返信を受信すると、ソースIP
はIP(192, 168, 1, 234)
になる.2枚のNICが独立して動作する場合は、正常にデータを送受信することができます.2枚のNICの
IP
を異なるセグメントに設定する必要があります.同時に、パソコン側はデバイス側と同じセグメントに設定する必要があります.例:
ホスト1:
IP: 192.168.0.88
MASK: 255.255.255.0
GATEWAY:192.168.0.1
デバイス1:
IP: 192.168.0.249
MASK: 255.255.255.0
GATEWAY:192.168.0.1
これにより、ホスト1とデバイス1とが正常に通信できる.
ホスト2:
IP: 192.168.1.88
MASK: 255.255.255.0
GATEWAY:192.168.1.1
デバイス2:
IP: 192.168.1.249
MASK: 255.255.255.0
GATEWAY:192.168.1.1
これにより、ホスト2とデバイス2とが正常に通信できる.
交差したらどうなるの?パケットツールを捕まえると、ターゲットが達成できないことがわかります.彼らはもう同じサブネット内にいないからです.
デバイス1とデバイス2が同じサブネット内にいたらどうなりますか?
ホスト:
IP: 192.168.0.88
MASK: 255.255.255.0
GATEWAY:192.168.0.1
デバイス1:
IP: 192.168.0.249
MASK: 255.255.255.0
GATEWAY:192.168.0.1
デバイス2:
IP: 192.168.0.248
MASK: 255.255.255.0
GATEWAY:192.168.0.1
現象:
ホスト->デバイス1:デバイス2->ホスト
ホスト->デバイス2:デバイス2->ホスト
そこで、私たちは結論を出しました.
IP
と正常に通信するしかありません.最初に追加したNICとの通信では、ip_rout
の関係で、最後にバインドしたNICのIP
を使用して返信します!