Example for DPWS MF server does not work

Hi all, I am a newbie with .NET Micro Framework. I have a problem and maybe I am missing something.
I am trying to make the DPWS HelloWorldServer_MF work in my Mountaineer Ethernet board. The same example works OK if I target the emulator.

After unsuccessfully trying .NET MF 4.2. Last week I altri tried .NET 4.3 MF beta that you announced here:
https://www.ghielectronics.com/community/forum/topic?id=13619

I did some investigation and found in this forum an old topic that deals with the problem I am facing now:
https://www.ghielectronics.com/community/forum/topic?id=8889&page=1
In this thread I did not find any solutions. I hoped that .NET 4.3 solved this issue.

In .NET MF 4.2 the example just crashes. The problem turns out with a SocketException generated from the DPWS stack in the Porting Kit.
The error code come is 10049 and comes directly from native code.
SocketException.ErrorCode = 10049 - WSAEADDRNOTAVAIL (Cannot assign requested address).
by looking closer to the issue the execption is generated within the “OnOpen” method of “UdpTransportBindingConfig” when the following instruction executes:
m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);

In .NET MF 4.3 the example does not crash but it still does not work.
If you look at “OnOpen” method in “UdpTransportBindingConfig” class you can see that the problem is hidden because the instructions that cause the Socket exception are within
a try/catch block that simply ignores exceptions when trtying to jojn multicast group:
try
{
m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddr );
m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);
}
catch{}

With .NET MF 4.3 installed in my device, I have captured with WireShark multicast packets generated by both HelloWorldServer_MF project (MF server) when executed in
Mountaineer Ethernet board and by the WCF client example running in a PC.
The result is that the Mountaineer board correctly sends “Hello” UDP messages using standard multicast address 239.255.255.250.
Unfortunately Mountaineer board does not answer the “Probe” UDP messages that the WCF client example sends using the same multicast address (239.255.255.250).
I have a high suspect that the Mountaineer Board does not detect the UDP messages sent by the PC because the “SetSocketOption” method still fails to join the multicast group.

I have then had a look at native code, LwIP 1.3.2 source code to figure out where this error could occur.
In sock.h the WSAEADDRNOTAVAIL is remapped to EADDRNOTAVAIL.
In arch.h EADDRNOTAVAIL is assigned a numeric code.
I think that the only place where this error could be generated is in ‘sockets.c’ module within the “lwip_setsockopt_internal” function.
In particular within this code fragment.
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{
/* If this is a TCP or a RAW socket, ignore these options. */
struct ip_mreq *imr = (struct ip_mreq *)optval;
ip_addr_t if_addr;
ip_addr_t multi_addr;
inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
if(optname == IP_ADD_MEMBERSHIP){
data->err = igmp_joingroup(&if_addr, &multi_addr);
} else {
data->err = igmp_leavegroup(&if_addr, &multi_addr);
}
if(data->err != ERR_OK) {
data->err = EADDRNOTAVAIL;
}
}
break;
Most likely “igmp_joingroup” function fails.

Questions:

  1. Are you aware of any work arounds or solution to this issue?
  2. Is this a problem in LWIP or in the Ethernet driver?
  3. How can you compile the LwIP stack in DEBUG mode so that I can see debug messages sent somewhere (I would prefer in Outpuit window within Visual Studio)?

Thank you in advance for your feedback.
Kind Regards
Karnize :wink:

Mountaineer 4.2 and 4.3 beta1 has an issue with receiving broadcast messages…

I reported this to CUNO, and my guess he is working on a fix, although I didn’t receive any acknowledgement from him is that regards…

Hello, today after a lot of investigations I have been finally able to find a “quick and dirty” workaround. Now I am able to successfully run the WCF/DPWS examples.
I and my colleague have created a patch in native code.
This is only a workaround, but I hope this helps in the release of a stable patch without side-effects.

FIRST PROBLEM AND WORK AROUND
In “STM32F4_ETH_driver.cpp” file, iniMACFFR() function, the MAC frame filter register initialization disables “pass all multicast”.
We therefore changed one line from
ETH->MACFFR &= ~ETH_MACFFR_PAM;
to
ETH->MACFFR |= ETH_MACFFR_PAM;

This change activates this option: Bit 4 PAM: Pass all multicast
When set, this bit indicates that all received frames with a multicast destination address (first bit in the destination address field is ‘1’) are passed.
When reset, filtering of multicast frame depends on the HM bit.

I am not sure if this is really the correct way to solve this issue.
However in case it is not, there should be something wrong with Bit 2 HM: Hash multicast. When set, MAC performs destination address filtering of received multicast frames according to the hash table.
When reset, the MAC performs a perfect destination address filtering for multicast frames,
that is, it compares the DA field with the values programmed in DA registers.

With the above change I am able to get multicast frames at the upper layer (IP).

SECOND PROBLEM AND WORK AROUND
In LwIP stack, ip.c module, ip_input function, there is a check if incoming multicast message shoudl be discarded or retained.
The following conditions:
(inp->flags & NETIF_FLAG_IGMP)
and
(igmp_lookfor_group(inp, &(iphdr->dest)))
are always false. The latter one because the function that should add endpoint to multicast group always fails.
By removing the above conditions, all multicast IP messages reach upper layer (UDP):

#if LWIP_IGMP
if (ip_addr_ismulticast(&(iphdr->dest))) {
if ( 1 ) {
// if ((inp->flags & NETIF_FLAG_IGMP)) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
netif = inp;
} else {
netif = NULL;
}
} else
#endif /* LWIP_IGMP */

This is only a work around. It is necessary to find a way to correctly manage NETIF_FLAG_IGMP and IGMP groups in this .NET MF port.

TEST SOLUTION
In order to test and debug this solution from within Visual Studio 2010 I have also “extracted” the DPWS stack from .NET MF 4.3 Porting Kit.
I have extracted the following system DLL Dpws, Dpws.Device, Dpws.Extensions. I had to make some “internal” classes and methods “public” in order to compile.

If you want to get the test solution for VS 2010, just let me how to attach a ZIP file to this forum.

I really hope that with these hints you are able to fix the multicast issue in next beta.
Thank you
BR
Karnize
:wink:

Thanks for the update and info, I would recommend you let Mountaineer Group (CUNO) know about this so they can try to correct it in their firmware…

as for the project you can always upload it to CodeShare here:
https://www.ghielectronics.com/community/codeshare

Cheers,
Jay.

Hi all, in codeshare I have inserted the modified sample DPWS server and WCF client solution that I have used to test native code “quick” fixes:
https://www.ghielectronics.com/community/codeshare/entry/814

The final solution should NOT IGNORE exceptions while adding the socket to multicast group.

Thanks for sharing, but wouldn’t one need the modified cpp files to test your solution?

or did you just modify the CS files and that did the job…?

Hi, the solution in code share only contains C# code.
Changes to C/C++ code are documented in one previous reply in this thread. There are actually only two little (but significant) changes,
In order to make the VS2010 solution work when the MF server runs in Mountaineering Board, it is necessary to apply changes to two files, rebuild the .NET framework, and deploy the new files to the board.

@ Karnize -
in file netif.c, go to the function struct netif * netif_add(…)
Replace

netif->flags &= (NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_DYNAMIC_DNS);

by

netif->flags |= (NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_DYNAMIC_DNS);

That way is better because "if ((inp->flags & NETIF_FLAG_IGMP)) " appears many places, can not cheat code only one place.

@ Dan -

I think that the following line of code is used to filter invalid flags, and keep just the valid.

netif->flags &= (NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_DYNAMIC_DNS);

Probably it is better to change the code where netif_add() is called.

For Mountaineer Ethernet board it is in STM32F4_ETH_lwip_adapter.cpp:

STM32F4_ETH_LWIP_Driver::Open(int index)

And add there something like:

g_STM32F4_ETH_NetIF.flag |= NETIF_FLAG_IGMP;

This has been done in other porting e.g. AT91 on SH7619.

What do you think?

Regards
Luca

Thanks to everyone! I’ve forwarded the link to this thread to the colleague who is working on the networking stuff.

@ lucapavy -

Open() will call netif_add(),

and in netif_add() function, this flag will be clear as you see :)))

So add that flag before calling netif_add(), it will be clear.
If call after calling netif_add(), it will be fine

And for us, we need full multicast, boardcast… so we tried add all back :)))

I think we have solved the problem!

I just add NETIF_FLAG_IGMP flag in STM32F4_ETH_ethhw_init() in STM32F4_ETH_lwip_adapter.cpp:

myNetIf->flags = NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;

Still necessary the modification in initMACFFR() in STM32F4_ETH_driver.cpp:

ETH->MACFFR |=  ETH_MACFFR_PAM;

With these no modifications are necessary in lwip.

Tested on real system, it works!

Regards

Hi all, special thanks to my colleague lucapavy that in the end found a good solution and not only a workaround !
With the native code changes proposed in the previous reply, Mountaineer board is able to handle multicast messages and WCF-DPWS communication examples work.
In addition now .NET framework does not throw any more a SocketException when calling the following instruction from within the managed stack of the Micro framework:

 m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);

The above instruction is used to join the multicast group in the “OnOpen” method of the “UdpTransportBindingElement” class.

I therefore recommend removing the try/catch block that someone added in.NET MF 4.3 managed stack for DPWS in order to hide this problem:

            try
            {
              m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddr);
              m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);
            }
            catch { }

I hope that you will add this patch to the next firmware releases.
Thank you
Best Regards

The fix isn’t in the just released beta.

It will probably get better traction if a work item is in place so I created one: https://netmf4stm32.codeplex.com/workitem/15

Please vote if you want this.

Nick

@ NickP, why on the STM32 port ? Is the issue only on that? Edit: yes, that’s the place, although I don’t know if every port in use uses that repository

I am running into the exact same issue with DPWS on the RAPTOR.

  1. Would this same fix apply to other boards?

  2. Do I need the entire source for the RAPTOR to modify as described below or is there a way add the fix without a complete rebuild?

  3. I have downloaded the ghiopensource but there is no raptor specific files…can I find them somewhere else?

I’ve been consuming this site for a week now…and it feels Great! Thanks.

Hi and welcome to the forum

Raptor is not an open-source board, it’s a premium board. It is unlikely this issue that this discusses is relevant to your situation, I’d start your own thread if you need specific help