Does any one have and code to initialize the RNG and get values from it?
Running into a problem with Interniche where on power up it uses the same initial socket number for outbound connects and if you reset the board too quickly the host on the other end will ignore the connection since it is marked as closed...
tom
...Looks like the code in the function udp_socket() needs to change too.
#define MINSOCKET 1200static unshort usocket = 0; /* next socket to grab */unshortudp_socket(void){ UDPCONN tmp; if (usocket < MINSOCKET) { /* logic for for init and after wraps */ usocket = (unshort)(cticks & 0x7fff); if (usocket < MINSOCKET) usocket += MINSOCKET; } /* scan existing connections, making sure socket isn't in use */ for (tmp = firstudp; tmp; tmp = tmp->u_next) { if (tmp->u_lport == usocket) { usocket++; /* bump socket number */ tmp = firstudp; /* restart scan */ continue; } } return usocket++;}
for some reason they AND cticks with 0x7FFF thus limiting the starting value to something between 1200 and 32767. That should probably be changed to cticks & 0x3fff + 49152.
Dave
It seems the port numbers do apply to both UDP and TCP. Take a look at the actual IANA info:
http://www.iana.org/assignments/port-numbers
I think I should change it in both places even though I'm not currently using UDP.
I learn more every day
Regards,
Dave
Mark,
Thanks for the info. I'll be making that change to be compliant with the IANA recommendations.
I did confirm that even the latest Rev. 3.2 Nichelite code that was updated in January the source port still starts at 1024. For those interested the parameter is NEXTLPORT_LL in the tcputil.c file.
Regards,
Dave Lundquist
Do these limits apply to local UDP port numbers as well?
In my older version of NicheLite, they appear to range from 1200 to 65535
(function udp_socket() and MINSOCKET in file m_udp.c)
A brief comment. I just spent a good amount of time tracking down a problem related to TCP/IP port numbers with the Nichelite stack. Embedded web clients would run fine in certain broadband net access locations and not others. The symptom was the units would startup and run for a while then hang. The problem turned out to be Scientific Atlanta cable modems that block port 1080. The interniche stack starts at 1024 and increments the source port up from there to 65535. If 1080 is blocked it dies. In my simple applicaition I just wrapped it at 1079 and it solved the problem.
Hi Dave
I think that it is a bit strange that the port numbers starts so low since these collide with well-known port numbers defined for specific uses. "Nowadays", to comply with IANA recommendations the range should start at 49152 and finish at 65535.
Earlier Windows TCP/IP stacks didn't comply (they used 1025 though 5000), but this has been 'corrected' in the newer versions to comply with the recommendations.Therefore I would also modify embedded system operation accordingly.
Regards
Mark
Referring back to the source of issue, you may wish to review the protocol design as well. There are valid reasons for TCP working this way. You may wish to take a look at:
http://www.developerweb.net/forum/showthread.php?t=5609
Chris
Hi Chris
I am not sure that there are any protocol design issue involved because it is clear that reuse of port number should be avoided and all protocol stacks try to do this. The difficulty is when the reuse avoidance lacks entropy and 'can' reuse a port which is still in the TIME WAIT state - this will usually only happen after a power up/reset when the client port number generator (should be adequately random) can't adequately seed its random port number generator to ensure the avoidance of a repeat.
Therefore it seems to be an issue of the quality of the random number generator. One which uses the same seed after a reset is destined to suffer from this problem since it requires only a reset either during an active TCP connection (the first since the SW started) or during the TIME WAIT period of the server after a close - then it will immedately hit the problem if it tries to establish the connection to teh same server again.
A random number generator which continues through a reset is one step ahead because it avoids the probem following a reset, but doesn't necessarily solve it after a power cycle.
Note too that according to the RFC also the client 'should' theoretically respect a 2MSL quiet time after a reset. This is however unrealistic since it means that even an embedded system should not make any TCP connections within 2 minutes of being turned on. I doubt if any company in the world could successfully market such a device which respected this requirement...;-). Users already get nervous when it takes more than 2..3s (the average autonegotiation time of the Ethernet in the M5223X) to get a device back on-line...
Regards
Mark
I agree with all you have said, and it is well said. Thanks. I suppose the short answer is good stacks handle this and stacks that do not are improved when they do. :smileyhappy:
The generation of the random number via the examples provided is a good solution. I am only raising the issue of there existing other possible things that should be considered. This is a difficult area of TCP to get robust. Your comments about power vs reset is a good example. Another is having the random generator generate all ports randomly rather than the first. This post provides a nice explaination of why:
http://www.nabble.com/TCP-port-reuse-causes--"No-route-to-host"-errors-td5295548.html
Chris
Hi Chris / Tom
To close this thread I have the following code example for Tom and results of some tests on the M52259 (with and without HW RD support).
1) Using the internal random number generator to define each new client port number there is (obviously) no problem.
2) Using the following code the results on the M52235 (RND disabled and this code used instead) the randomness is adequate for the task in hand - both for power cycle (the internal RAM is in fact very random on power up in this chip - absolutely no obvious patterns) and for warm restarts.
extern void fnInitialiseRND(unsigned short *usSeedValue){ if ((*usSeedValue = *ptrSeed) == 0) { // we hope that the content of the random seed is random after a power up *usSeedValue = 0x127b; // we must not set a zero - so we set a fixed value } // after a reset it should be well random since it will contain the value at the reset time *ptrSeed = fnRandom(); // ensure that the seed value is modified between resets}
This routine is called when the board is initialised.
*usSeedValue is a pointer to the seed used in a pseudo-random number generator (we use a 16 bit one - there are many examples and they are only a few lines code in length).
ptrSeed is a global pointer to an otherwise unused 16 bit ram location in internal SRAM. We actually put it on the very top of stack when the system is initialised and it is never overwritten by any other code (nor BSP initialisation) - the linker doesn't in fact know of its existence. This RAM location has a 'random' value after power up so the seed to the pseudo-random number generator is also 'random'.
Note that a seed of 0x0000 is illegal and, should it ever 'randomly' occur, a different fixed value is seeded (as protection).
The first use of the pseudo-random number generator which has now been seeded is to generate a new value for our 'random' seed. This means that when the board is reset its new 'random' seed value is again different but still 'random' in nature.
As I test I got the board to get the present data and time for a known time server (time-a.nist.gov 129.6.15.28 NIST, Gaithersburg, Maryland). I noted the port number that the client used (it randomly gets a new one on each use [every new TCP connection] using the pseudo-random generator in the dynamic port range 49152...6553) and verified that it was truely 'random' in nature after each power cycle and each warm reset, thus confirming the suitability of this method for this application.
Finally I did a test where I forced the same port number to be used, repeating at about 10s intervals.
I think the server designers have also been reading some of the discussions that Chris has referenced because this server actually accepted each one with no complaints.....!
Regards
Mark
- OS, TCP/IP stack, USB, device drivers and simulator for M5221X, M5222X, M5223X, M5225X. One package does them all - "Embedding it better..."
Hi Tom
Are you sure that you are using the M52233 since this has no random number generator.
Only the following chips do: M52235, M52255 and M52259
Attempting to access it in other devices will result in an access violation.
Assuming you have one in your device, there are two modes (using sleep and free run).
Free run is the simplest but consumes more power:
RNGER = 0x1234; // additional entropy (not really needed)
RNGCR = (RND_CI | RND_IM | RND_GO); // start generation of first number (ready after 256 cycles)
...
random_number = RNGOUT; // read new random number
Sleep mode requires:
RNGCR = (RND_CI | RND_IM | RND_SLM); // initialisation: set sleep mode
RNGCR = (RND_CI | RND_IM | RND_GO); // remove from sleep mode
while (!(RNGSR & RND_ORL_MASK)) {} // wait for a random number to be available (usually already waiting - max. 256 cycles after GO)
random_number= RNGOUT;
RNGCR = (RND_CI | RND_IM | RND_GO | RND_SLM); // set sleep mode again
Regards
Mark
You have a good point there!
Ok any suggestions of the next best way to get a pseudo random number?
Often cticks is used, but during power up it is generally the same...
Any other registers that can be used to return varying values?
Like I said I m just using it to change the initial tcp port interniche uses for the first connection.
tom
Hi Tom
If you want good entropy you could configure an ADC input and read its value - best connected to a noise diode.
In the uTasker project we use a pseudo random generator which has a seed at a RAM location outside of the normal memory map so that startup code doesn't initialise it. Between resets it means the pseudo-random number gets continuously incremented (sind the reset doesn't destroy the old value). At power up it relies on the randomness of the RAM content - which is (unfortunately) not that perfect since they do often take the same value... but I don't recall any difficulties with the technique (also no reports on its effectiveness....)
In case one of the devices with RNG are use, it automatically uses it for this purpose.
Regards
Mark