Forum Discussion
Altera_Forum
Honored Contributor
16 years agoHow do Nios-II handle IP address change during the TCP/IP connection?
Dear all,
I have problem with changing IP address in the FPGA board. Here is my case, let say I have a FPGA board which is connected to PC. The PC sends a command to the FPGA that asks the FPGA to change its IP address to a new given IP address. Here is my idea to handle this task :- After receiving IP changes command from PC, both FPGA and PC terminate their TCP/IP connection by close their socket.
- The FPGA does the IP changes mechanism
- Both FPGA and PC initiate a new TCP/IP connection like usual
- The FPGA sends acknowledgement to the PC to tell that it already changes its IP address successfully.
- Terminate the previous TCP/IP connection (close the exist socket)
- Assign new IP address to the FPGA (I have made a new function called 'change_ip' which is basically same as get_ip_addr function provided by altera)
- Initiate new TCP/IP connection (create, bind, listen socket)
: See STDERR for expanded diagnosis translation.
: Bind failed
: ERRNO: :
: See STDERR (FAULT_LEVEL is SYSTEM).
: FAULT_LEVEL is SYSTEM.
: FATAL Error, Restart required.
: Locking scheduler - endless loop. I also tried to kill the previous "inet main" and "clock tick" tasks, but in the end it also ends up with the same error message. Anybody know how is the correct procedure to change FPGA's IP address? :confused: :confused: Thanks for any comments or suggestions!27 Replies
- Altera_Forum
Honored Contributor
Take a look at the function "set_ipaddr()" inside the following file:
C:\altera\91\nios2eds\components\altera_iniche\UCOSII\src\misclib\nrmenus.c This will indicate how the InterNiche stack performs a ip address change. See if that helps. Jake - Altera_Forum
Honored Contributor
Hi jakobjones, thanks for your reply. Finally I got a clue.
I will check the function you mentioned and tell you the result later! ;) If anybody have other suggestions, feel free to share it :) - Altera_Forum
Honored Contributor
Hi Jakobjones!
I've checked the "set_ipaddr()" function and "alt_iniche_dev.c", then I made my own function to change the ip address. Here is the code :
There was no error either during the compilation or after the program execution, but the Nios' IP address didn't change (I've checked it by ping the Nios from my pc). It still used the old IP address. Do you know what's wrong with my code? I'm thinking that I need to reset the NicheStack or force the NicheStack to read the new assigned IP address. But I don't know how to do that. Hopefully you can help me.. Thanks before.int change_ip (int dhcp_actv) { alt_iniche_dev *p_dev; NET p_net; ip_addr ipaddr, netmask, gw; NetInfo new_ip; new_ip.ipaddr_in = 192; new_ip.ipaddr_in = 168; new_ip.ipaddr_in = 1; new_ip.ipaddr_in = 3; new_ip.netmask_in = 255; new_ip.netmask_in = 255; new_ip.netmask_in = 255; new_ip.netmask_in = 0; new_ip.gw_in = 192; new_ip.gw_in = 168; new_ip.gw_in = 1; new_ip.gw_in = 1; p_dev -> p_net = nets; // Get the new ip address printf(" Get the new ip address\n"); if(dhcp_actv) p_net -> n_flags |= NF_DHCPC; else { IP4_ADDR( ipaddr, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in ); IP4_ADDR( netmask, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in ); IP4_ADDR( gw, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in ); p_net -> n_ipaddr = ipaddr; p_net -> snmask = netmask; p_net -> n_defgw = gw; } return 0; } - Altera_Forum
Honored Contributor
Ah.. I got it! I found the mistake in my code.
The mistake is here : p_dev -> p_net = nets[0]; It should be p_net = nets[0]; Thank you all! - Altera_Forum
Honored Contributor
Sorry to re-open this thread, but I had the same problem.
Your code worked for me, except for DHCP. This one does:
In dhc_setup(), calling dhc_first() fails , probably because the port is already in use. So I just called dhc_second, is it's done in dhc_setup(). Works for me.if(dhcp_actv) { p_net -> n_flags |= NF_DHCPC; // dhc_setup(); // fails, because port is in use? dhc_state_init(0, FALSE); /* Put DHCPClient in INIT-REBOOT state */ int e = dhc_second(); /* To send the DISCOVER/REQUEST pkt */ if (e) printf("DHCP returned error %i.\n", e); } - Altera_Forum
Honored Contributor
@ Jakobjones
I have created this following function to change the ethernet's IP address during the TCP/IP connection
Then after executing the above code, I re-initialize the TCP/IP connection (socket creation, bind, listen, select). The above code could work correctly. However, it only could change the IP address for two times in sequence. In the third times, it would be error. The error message said that the program couldn't find any ethernet card anymore. From debugging my code, I noticed that whenever I assigned a new IP address to my ethernet, the Nios-II thought that as IP address for another ethernet card. Since in the default niche configuration Nios-II only supports for two ethernet cards, in the third times of new IP address assignment, Nios-II will generate error notification. Do you know how to solve this problem? Is there any function to flush the ethernet configuration, such that whenever I assign a new ip address, the Nios will notice it as for the same ethernet card? :( And another question is about the DHCP connection. Since in this current project I want to provide on-fly DHCP / manual IP address assignment, I disable the 'dhcp client' option in the altera niche. For re-initialize DHCP function do you think it is enough by assigning this single code :int change_ip (int dhcp_actv, NetInfo new_ip) { NET p_net; ip_addr ipaddr, netmask, gw; p_net = nets; // for multi network interface, check file alt_iniche_dev.c // Get the new ip address printf(" Get the new ip address\n"); if(dhcp_actv) p_net -> n_flags |= NF_DHCPC; else { IP4_ADDR( ipaddr, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in ); IP4_ADDR( netmask, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in ); IP4_ADDR( gw, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in ); p_net -> n_ipaddr = ipaddr; p_net -> snmask = netmask; p_net -> n_defgw = gw; } netmain_init(); iniche_net_ready = TRUE; return 0; }
Or are there anything else that I need to configure? :confused: Thank you. I'm looking forward any help from you or anyonep_net -> n_flags |= NF_DHCPC - Altera_Forum
Honored Contributor
As far as I have seen, there is no need to call netmain_init().
Is there a reason why you are executing it? If you disable DHCP in the BSP, there is no DHCP code in your project. It is surrounded by -ifdef everywhere, and won't get included. It will be better to change get_ip_addr(), and set use_dhcp = 0 there. This function is there for customization, so that's the point to start. I'm not sure this will do it, maybe one has to disable the NF_DHCPC flag (wherever that gets set; I have seen it already, but can't remember where). To enable DHCP then, you can use my code as above. The 3 times problem I have not seen yet, as I have just changed my IP Address 2 times: DHCP->static->DHCP. I'll try tomorrow. - Altera_Forum
Honored Contributor
Hi mcr42! Thank you for your reply :)
I thought that we used netmain_init() to apply new IP address that we just assigned. Otherwise, the ethernet card would not notice the new ip address, am I correct? Well, I will try not to call netmain_init() after assign a new IP address, and see what happen. Maybe netmain_init() is the reason for my three times problems (fyi, on that time I tried to do static --> static --> static ip address assignment). I just read your DHCP configuration code today, I will also try it and inform you about the results. Thanks! :) - Altera_Forum
Honored Contributor
I have done a small test, 7 changes static->static, and it seems to be stable.
Even when doing 4 times DHCP->static->DHCP, there is no problem. It might be neccessary to wait until DHCP has finished (which is not the case when DHC_second returns). Depending on the network the DHCP response takes a moment. A newly initiated connection might still use the old IP. When the response arrives after the new IP was assigned, it will not be seen, and the connection times out. Also, reading the code again, dhc_second() does not evalutate the NF_DHCPC flag. Also, there is a note that dhc_second() should be called every once in a while to update leases. Therefore I think it's neccessany to disable the DHCPClient via the state variable:
So my change_ip() looks like this now:if(dhcp_actv) { p_net -> n_flags |= NF_DHCPC; dhc_state_init(iface, FALSE); /* Put DHCPClient in INIT-REBOOT state */ ...... } else { p_net -> n_flags &= ~NF_DHCPC; dhc_set_state(iface, 0); /* set interface state to DHCS_UNUSED */ ...... }typedef struct { alt_u8 ipaddr_in; alt_u8 netmask_in; alt_u8 gw_in; } NetInfo; int change_ip (NetInfo new_ip, int dhcp_actv) { // alt_iniche_dev *p_dev; NET p_net; ip_addr ipaddr, netmask, gw; int iface = 0; // number of interface to use p_net = nets; // Get the new ip address printf(" Get new ip address:\n"); if(dhcp_actv) { p_net -> n_flags |= NF_DHCPC; dhc_state_init(iface, FALSE); /* Put DHCPClient in INIT-REBOOT state */ } else { p_net -> n_flags &= ~NF_DHCPC; dhc_set_state(iface, 0); /* put DHCPClient in DHCS_UNUSED state */ IP4_ADDR( ipaddr, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in, new_ip.ipaddr_in ); IP4_ADDR( netmask, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in, new_ip.netmask_in ); IP4_ADDR( gw, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in, new_ip.gw_in ); p_net -> n_ipaddr = ipaddr; p_net -> snmask = netmask; p_net -> n_defgw = gw; } // dhc_setup(); // fails, because port is in use? int e = dhc_second(); /* To send the DISCOVER/REQUEST pkt */ if (e) printf("DHCP returned error %i.\n", e); return 0; } - Altera_Forum
Honored Contributor
Thanks for sharing your code. It looks great!
Now I'm trying using your code. Somehow, my Nios is always failed when it tries to bind the new socket. Do you have any suggestion about this? Thank you.