Skip to content

Static DHCP Lease not working #6031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 of 6 tasks
mbm60 opened this issue Apr 30, 2019 · 19 comments
Open
5 of 6 tasks

Static DHCP Lease not working #6031

mbm60 opened this issue Apr 30, 2019 · 19 comments
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.

Comments

@mbm60
Copy link
Contributor

mbm60 commented Apr 30, 2019

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: ESP-12
  • Core Version: 2.5.0
  • Development Env: Arduino IDE
  • Operating System: Windows

Settings in IDE

  • Module: Generic ESP8266 Module
  • Flash Mode: Dout
  • Flash Size: 4MB
  • lwip Variant: v2 Lower Memory
  • Reset Method: ck
  • Flash Frequency: 40Mhz
  • CPU Frequency: 80Mhz
  • Upload Using: SERIAL
  • Upload Speed: 115200

Problem Description

unknown device must get ip 192.168.0.102 but never get that ip Sometimes get IP 192.168.0.100 and sometimes 192.168.0.2

MCVE Sketch

#include <ESP8266WiFi.h>

const char *ssid = "ESPap";
const char *password = "thereisnospoon";

IPAddress apIP(192, 168, 0, 1);

void setup() {
  struct station_info *stat_info;
  String address;
  uint8_t i;

  uint8 mac_CAM[6] = { 0x00, 0x0C, 0x43, 0x01, 0x60, 0x15 };
  uint8 mac_PC[6] = { 0xb4, 0x52, 0x7e, 0x9a, 0x19, 0xa5 };

  Serial.begin(74880);
  Serial.println();
  Serial.println("Configuring access point...");

  WiFi.persistent(false);
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));

  wifi_softap_add_dhcps_lease(mac_CAM);  // always 192.168.0.100
  wifi_softap_add_dhcps_lease(mac_PC);   // always 192.168.0.101

  WiFi.softAP(ssid, password);
  
  Serial.print("AP IP address: ");
  Serial.println(WiFi.softAPIP());
  Serial.println("HTTP server started");
  
  while ( WiFi.softAPgetStationNum() == 0 ) {
    delay ( 500 ); Serial.print ( "." );
  }

  stat_info = wifi_softap_get_station_info();
  while (stat_info != NULL) {
    address = IPAddress(stat_info->ip).toString();
    Serial.print("client= ");
    Serial.print(i);
    Serial.print(" IP adress is = ");
    Serial.print((address));
    Serial.print("  Mac : ");
    Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X", MAC2STR(stat_info->bssid));
    stat_info = STAILQ_NEXT(stat_info, next);
    i++;
    Serial.println();
  }
}

void loop() {
}

Debug Messages

ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v951aeffa
~ld

SDK:3.0.0-dev(c0f7b44)/Core:2.5.0=20500000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1/BearSSL:6778687

Configuring access point...
[APConfig] local_ip: 192.168.0.1 gateway: 192.168.0.1 subnet: 255.255.255.0
[APConfig] DHCP IP start: 192.168.0.100
[APConfig] DHCP IP end: 192.168.0.200
bcn 0
del if1
usl
add if1
dhcp server start:(ip:192.168.0.1,mask:255.255.255.0,gw:192.168.0.1)
bcn 100
AP IP address: 192.168.0.1
HTTP server started
..........
wifi evt: 7
add 1
aid 1
station: 40:4a:03:57:a0:de join, AID = 1
wifi evt: 5
wifi evt: 9
client= 0 IP adress is = 192.168.0.2  Mac : 40:4A:03:57:A0:DE
@devyte
Copy link
Collaborator

devyte commented Apr 30, 2019

Ref:#5594
CC @SmartBlug

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Apr 30, 2019
@SmartBlug
Copy link
Contributor

Where was a change in WiFi.softAP(ssid, password);
now, call to WiFi.softAP() remove the leases from the list (call to node_remove_from_list()).
As a result, the leases are empty

@SmartBlug
Copy link
Contributor

Debug from APConfig is false, it says 192.168.0.100 but in reality, first IP address has not been updated to this value.
When APConfig start DHCP with call to wifi_softap_dhcps_start(), the first @ip is assigned with softap_ip +1 in wifi_softap_init_dhcps_lease()

dhcps_lease.start_ip.addr = softap_ip | local_ip;

This is new and was not the case in the past because the first @ was 100 as described in softAPConfig
Then now, first ip of the pool is @ip of AP +1

When WiFi.softAP(ssid, password); is called, there is a call to wifi_softap_set_config_current() and this function remove the nodes from the list with calls to node_remove_from_list()

I do not have access to the code of wifi_softap_set_config_current() so there is no way to remove it and understand why they've done it.
If you move your calls to wifi_softap_add_dhcps_lease() after WiFi.softAP(ssid, password) this is working.

Your code is now :

#include <ESP8266WiFi.h>

const char *ssid = "ESPap";
const char *password = "thereisnospoon";

IPAddress apIP(192, 168, 0, 1);

void setup() {
  struct station_info *stat_info;
  String address;
  uint8_t i;

  uint8 mac_CAM[6] = { 0x00, 0x0C, 0x43, 0x01, 0x60, 0x15 };
  uint8 mac_PC[6] = { 0xb4, 0x52, 0x7e, 0x9a, 0x19, 0xa5 };

  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");

  WiFi.persistent(false);
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));

  WiFi.softAP(ssid, password);
  
  wifi_softap_add_dhcps_lease(mac_CAM);  // always 192.168.0.2
  wifi_softap_add_dhcps_lease(mac_PC);   // always 192.168.0.3

  Serial.print("AP IP address: ");
  Serial.println(WiFi.softAPIP());
  Serial.println("HTTP server started");
  
  while ( WiFi.softAPgetStationNum() == 0 ) {
    delay ( 500 ); Serial.print ( "." );
  }

  stat_info = wifi_softap_get_station_info();
  while (stat_info != NULL) {
    address = IPAddress(stat_info->ip).toString();
    Serial.print("client= ");
    Serial.print(i);
    Serial.print(" IP adress is = ");
    Serial.print((address));
    Serial.print("  Mac : ");
    Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X", MAC2STR(stat_info->bssid));
    stat_info = STAILQ_NEXT(stat_info, next);
    i++;
    Serial.println();
  }
}

void loop() {
}

Could you confirm that it's working and now, your first unknown device is always 192.168.0.4 ?

@mbm60
Copy link
Contributor Author

mbm60 commented May 1, 2019

@SmartBlug , I did your suggestion and moved wifi_softap_add_dhcps_lease() after WiFi.softAP and its working. my first unknown device ip is 192.168.0.4. thanks

My new question is why config debug tells the start ip is 192.168.0.100 but the real start ip is 192.168.0.2 and how can i change the start and end ip?

@SmartBlug
Copy link
Contributor

This is because the code from softAPConfig() and from wifi_softap_init_dhcps_lease() are not compatible.
Developper of softAPConfig() decided to start with +100 and developper of softap_init_dhcps_lease() decided to start with +1...
I can modify this part but as it's not my code, I don't want to change without their approval.
@devyte , do you know who own this part of the code ?

@mbm60
Copy link
Contributor Author

mbm60 commented May 1, 2019

@SmartBlug No matter who wrote that part of the code, you can create pull request and make the changes you want.

@SmartBlug
Copy link
Contributor

Yes and no, there is probably a reason why they changed and do not respect +100 as in the past...
Of course I can change the code and create a PR but before, I would like to know why they've done this change

@mbm60
Copy link
Contributor Author

mbm60 commented May 1, 2019

where is the function "wifi_softap_init_dhcps_lease()"? i cant find it in library's file.

@SmartBlug
Copy link
Contributor

/tools/sdk/lwip2/builder/glue-lwip/esp-dhcpserver.c

@mbm60
Copy link
Contributor Author

mbm60 commented May 1, 2019

/tools/sdk/lwip2/builder/glue-lwip/esp-dhcpserver.c

Yes but that file need to build and someone must do that.

@devyte
Copy link
Collaborator

devyte commented May 1, 2019

The lwip glue is used to build the lwip libs, and the lwip libs are used to build our core. If you change those source files, you must first rebuild lwip from sources, then rebuild the core.
lwip2*

@d-a-v
Copy link
Collaborator

d-a-v commented May 1, 2019

do you know who own this part of the code ?

You can use the blame button / git blame command to see the commit comments around these lines

@devyte
Copy link
Collaborator

devyte commented May 1, 2019

The code in softAP and softAPConfig is ours, so changes there can be discussed here.
The start IP should be configurable on our end, which I understand is what the lease() call is for?

    struct dhcps_lease dhcp_lease;
    IPAddress ip = local_ip;
    ip[3] += 99;
    dhcp_lease.start_ip.addr = ip.v4();
    DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());

    ip[3] += 100;
    dhcp_lease.end_ip.addr = ip.v4();
    DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());

    if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
        DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
        ret = false;
    }

Edit: NVM, I was confusing init_lease() with set_lease()

@SmartBlug
Copy link
Contributor

@devyte , do you know where is wifi_softap_set_config_current() that seems to decide to remove the nodes from the list ?
This is called by WiFi.softAP(ssid, password);

@devyte
Copy link
Collaborator

devyte commented May 1, 2019

The code in /tools/sdk/lwip2/builder/glue-lwip/esp-dhcpserver.c is also owned by us and could therefore be changed as well, if it makes sense to do so. However, care must be taken with the function signatures.

@devyte
Copy link
Collaborator

devyte commented May 1, 2019

I think the set_config_current() calls aren't ours, they're in the sdk.

@d-a-v
Copy link
Collaborator

d-a-v commented May 1, 2019

wifi_softap_set_config_current() is in the nonos-sdk:

This API can be called only if the ESP8266 SoftAP is enabled.
Note
• This configuration will be saved in flash system parameter area if changed.
• In SoftAP + Station mode, the ESP8266 SoftAP will adjust its channel
configuration to be the as same as that of the ESP8266 Station. More details
please see Appendix.A.

@Spongman
Copy link

Spongman commented Mar 26, 2020

any news on this bug (and the duplicates) ?

if you pass a netmask smaller than a /24 (eg a /29), then the softAP hands out invalid DHCP leases.

for example, for a 10.0.0.0/29 network, the valid addresses are 10.0.0.1 -> 10.0.0.6, however the first address it hands out is 10.0.0.100.

also, this 'local_ip+99' calculation is clearly wrong if local_ip is near the end of the network, even for /24 networks. it's perfectly valid for local_ip to be 10.0.0.254 in the 10.0.0.0/24 network, and this would result in an overflow and the dhcp range again being in the wrong network.

here's something that i came up with that gives reasonable defaults for smaller networks:

auto network_start = lwip_ntohl(info.gw.addr & info.netmask.addr);
auto network_size = ~lwip_ntohl(info.netmask.addr);
auto network_end = network_start + network_size;

DEBUG_WIFI("[APConfig] DHCP Network Start: %s\n", IPAddress(lwip_htonl(network_start)).toString().c_str());
DEBUG_WIFI("[APConfig] DHCP Network End:   %s\n", IPAddress(lwip_htonl(network_end)).toString().c_str());
DEBUG_WIFI("[APConfig] DHCP Network Size:  0x%x\n", network_size);

struct dhcps_lease dhcp_lease;
dhcp_lease.start_ip.addr = lwip_htonl(network_start + network_size * 99 / 255 + 1);
DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", IPAddress(dhcp_lease.start_ip.addr).toString().c_str());

dhcp_lease.end_ip.addr = lwip_htonl(network_start + network_size * 200 / 255);
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", IPAddress(dhcp_lease.end_ip.addr).toString().c_str());

this produces the following DHCP pools for these different 10.0.0.0/xx networks (note that the /24 pool is the same as the existing code, assuming a .1 local_ip):

Netmask Network Start Network End Pool Start Pool End
/24 10.0.0.0 10.0.0.255 10.0.0.100 10.0.0.200
/25 10.0.0.0 10.0.0.127 10.0.0.50 10.0.0.99
/26 10.0.0.0 10.0.0.63 10.0.0.24 10.0.0.49
/27 10.0.0.0 10.0.0.31 10.0.0.13 10.0.0.24
/28 10.0.0.0 10.0.0.15 10.0.0.6 10.0.0.11
/29 10.0.0.0 10.0.0.7 10.0.0.3 10.0.0.5
/30 10.0.0.0 10.0.0.3 10.0.0.2 10.0.0.2

@d-a-v
Copy link
Collaborator

d-a-v commented Mar 26, 2020

DHCP server is going to be brought into this core when #6680 is merged, after 2.7.0 is released.
It will be easier to improve it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.
Projects
None yet
Development

No branches or pull requests

5 participants