Forum: Mikrocontroller und Digitale Elektronik lwIP UDP empfangen


von Godi S. (godi22)


Lesenswert?

Hallo,

Ich habe ein AVR32 Board auf dem FreeRTOS + lwIP läuft.
Ich möchte von Matlab aus ein UDP Paket versenden und dies mit dem AVR32 
empfangen.
UDP Paket versenden vom AVR32 und empfangen von Matlab funktioniert. 
Anpingen funktioniert auch, nur das empfangen nicht. :(

IP Adresse vom PC mit Matlab: 143.205.120.123
IP Adresse vom AVR32: 143.205.120.211

Mein Task: (es ist nur dieser Task aktiv)
1
void receiveUDP(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port){
2
  if (p != NULL) {      
3
    LED_Toggle(LED3_GPIO);
4
  }
5
}
6
7
8
9
void vRunTask( void * pvParameters ) {    
10
11
  // Initialize the xLastWakeTime variable with the current time.
12
  portTickType xLastWakeTime = xTaskGetTickCount();
13
    
14
  struct udp_pcb *udp_pcb_run = udp_new();
15
    
16
  struct ip_addr *ip_avr32;
17
  IP4_ADDR(ip_avr32, 143,205,120,211);
18
  
19
  struct ip_addr *ip;
20
  IP4_ADDR(ip, 143,205,120,123);
21
  
22
  err_t err;
23
  
24
  err = udp_bind(udp_pcb_run, ip_avr32, 1234);
25
  if (err != ERR_OK)  {
26
    LED_On(LED3_GPIO);
27
  }
28
  
29
  err = udp_connect(udp_pcb_run, ip, 1234);
30
  if (err != ERR_OK)  {
31
    LED_On(LED3_GPIO);
32
  }
33
  
34
  udp_recv(udp_pcb_run, receiveUDP, NULL);
35
      
36
    
37
  for( ;; ) {
38
    // Wait for the next cycle.
39
    vTaskDelayUntil( &xLastWakeTime, configTICK_RATE_HZ );    
40
                
41
    LED_Toggle(LED0_GPIO);
42
    
43
  }
44
}

Wenn ich von Matlab ein Paket versende dann bekomme ich vom AVR32 immer 
die Antwort: Destination Unreachable (Port unreachable)

Hat jemand eine Idee warum dies so ist?
Bin schon am verzweifeln weil ich es mir einfach nicht erklären kann was 
da nicht passt! :(

LG
godi

von Stefan (Gast)


Lesenswert?

"Destination Unreachable" kommt immer von einem Router, Switch oder vom 
IP-Stack des Absenders selbst.

Da in Deinem Fall beide Systeme im gleichen Netz hängen, besteht 
anscheinend keine Verbindung zwischem Deinem Router und dem AVR32 (er 
wantwortet nicht auf ARP Pakete).

Warscheinlich kannst DU ihn auch nicht anpingen, stimmts?

von Godi S. (godi22)


Lesenswert?

Doch ich kann ihn anpingen. Der AVR32 antworted auf alle 4 Pakete.

Wenn ich ein UDP Paket zum AVR32 sendet wird auch im lwIP die Funktion 
ip_input() aufgerufen. Diese ruft auch die Funktion udp_input() auf. 
Jedoch wird dort die ICMP Message mit den nicht erreichten Port 
zurückgesendet.

In diesem Code in der udp_input() Funktion:
1
#if LWIP_ICMP
2
      /* No match was found, send ICMP destination port unreachable unless
3
         destination address was broadcast/multicast. */
4
      if (!broadcast &&
5
          !ip_addr_ismulticast(&current_iphdr_dest)) {
6
        /* move payload pointer back to ip header */
7
        pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
8
        LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
9
        icmp_dest_unreach(p, ICMP_DUR_PORT);
10
      }
11
#endif /* LWIP_ICMP */

von Fritz (Gast)


Lesenswert?

godi S. schrieb:
> Doch ich kann ihn anpingen. Der AVR32 antworted auf alle 4 Pakete.
Und Du bist sicher, das der AVR antwortet und nicht irgendein anderes 
Gerät?

Fritz

von Godi S. (godi22)


Angehängte Dateien:

Lesenswert?

Ja es ist der AVR32.

Mir ist aber jetzt gerade was anderes aufgefallen.
Ich überwache mit Wireshark den Traffic und da steht beim gesendeten UDP 
Paket das die Checksumme des Headers nicht stimmt. Im Anhang noch ein 
Screenshot von Wireshark.

In Matlab R2011b verwende ich folgenden code:
1
clear all;
2
close all;
3
clc;
4
5
u=udp('143.205.120.211', 1234, 'LocalPort', 1234);
6
fopen(u);
7
8
fwrite(u,65:74);
9
10
fclose(u);



Edit:
Portnummern habe ich im Beitrag die falschen geschrieben

von Godi S. (godi22)


Lesenswert?

Hmm...

Habe jetzt mal alle Pakete überprüft die vom PC gesendet werden.
Da ist anscheinend überall der Header defekt (auch beim Ping). Also 
dürfte es nicht daran liegen.

von Thorsten (Gast)


Lesenswert?

Höchstwahrscheinlich hast Du eine intelligente Netzwerkkarte, die die 
Checksummenberechnung macht. Dann haben die lokal gesendeten Pakete im 
Dump eine falsche Checksumme, auf der Leitung sollte sie dann aber 
stimmen.

von Godi S. (godi22)


Lesenswert?

Ok, Danke für die Info.

Hat jemand noch eine Idee warum das Empfangen nicht funktioniert?
Kann es sein, dass die Funktion udp_bind nicht richtig funktioniert, bzw 
dass ich da noch falsche Parameter habe? (Fehler wird von der Funktion 
keiner zurückgegeben)

von Jojo S. (Gast)


Lesenswert?

ersetze mal im udp_bind die 'ip_avr32' durch 'IP_ADDR_ANY'.

von Godi S. (godi22)


Lesenswert?

Jojo S. schrieb:
> ersetze mal im udp_bind die 'ip_avr32' durch 'IP_ADDR_ANY'.

Leider, funktioniert auch nicht. :(

von Jojo S. (Gast)


Lesenswert?

dann sollte man noch die Portnummer mit dem 'htons(1234)' setzen. Damit 
wird von der internen auf die feste Netzwerk Darstellung der Werte 
konvertiert.

von Godi S. (godi22)


Lesenswert?

Mit htons funktionierts leider auch nicht. :(

von Marius M. (marius1m)


Lesenswert?

Hi godi,

hast du dein Problem lösen können? Ich habe das selbe Problem mit meinem 
lwip-Stack.
Ich verwende die Version 1.4.1 auf dem NiosII, Cyclone V.
Der Stack an sich funtioniert, ich kann UDP-Packete versenden und diese 
auch mit Wireshark ansehen. TCP-Packe werden sowohl gesendet, als auch 
empfangen. Ich kann den Webserver via Firefox anzeigen. Nur das 
Empfangen von UDP-Packeten funkioniert nicht.

Vielen Dank für die Hilfe
Gruß
Marius

von Uwe B. (derexponent)


Lesenswert?

@Marius,


benutzt du den gleichen Quellcode für die Initialisierung
wie "godi S."

falls ja, lösch mal diese Zeile :
1
err = udp_connect(udp_pcb_run, ip, 1234);

und benutzte beim senden von UDP-Protokollen
1
  udp_sendto(...);

mit Angabe der Ziel-IP Adresse
(statt die Funktion "udp_send(...)"

Gruss Uwe

von Marius M. (marius1m)


Lesenswert?

Hi Uwe,

danke für die schnelle Antwort. Das Versenden einens Paketes 
funktioniert bei mir mit folgender Funktion ganz gut.

1
int udp_send_from_ISR( int *pData, u32_t length)
2
{
3
  struct udp_pcb *send_pic_udp_pcb;
4
  struct ip_addr remote_ip_addr;
5
  struct pbuf *p;
6
7
  err_t err_msg;
8
9
  IP4_ADDR( &remote_ip_addr, REMOTE_IP_ADDR_0, REMOTE_IP_ADDR_1, REMOTE_IP_ADDR_2, REMOTE_IP_ADDR_3);
10
11
  send_pic_udp_pcb = udp_new();
12
  
13
  err_msg = udp_bind( send_pic_udp_pcb, IP_ADDR_ANY, PC_PORT);
14
  
15
  if(err_msg != ERR_OK )  print_err_msg(err_msg);
16
  else
17
  {
18
    err_msg = udp_connect(send_pic_udp_pcb, &remote_ip_addr, PC_PORT); // ID_ADDR_BROADCAST
19
  
20
    if( err_msg != ERR_OK )
21
      print_err_msg(err_msg);
22
    else
23
    {
24
      p = pbuf_alloc( PBUF_TRANSPORT, length, PBUF_RAM);
25
      if( p == NULL)
26
      {
27
        printf("Faild to allocate Mem for pbuf \n");
28
        return 0;
29
      }
30
      else
31
      {
32
        p->payload = pData;
33
        p->tot_len = length;
34
35
        err_msg = udp_send( send_pic_udp_pcb, p);
36
      
37
        if(err_msg != 0) print_err_msg(err_msg);
38
39
        pbuf_free(p);
40
        udp_disconnect(send_pic_udp_pcb);
41
        udp_remove(send_pic_udp_pcb);
42
        return 1;
43
      }
44
    }
45
  }
46
return 0;
47
}

Da ich diese Funktion recht häufig aufrufe ist es vielleicht nicht die 
schönste Lösung, bei jedem Aufruf einen neuen UDP-Protokollblock 
aufzusetzten, aber so funktioniert es erstmal.

Mein Problem liegt beim Empfangen von UDP-Pkgs. Mein Lösungsansatz sieht 
so aus:

1
#define REMOTE_IP_ADDR_0 192
2
#define REMOTE_IP_ADDR_1 168
3
#define REMOTE_IP_ADDR_2   1
4
#define REMOTE_IP_ADDR_3 255
5
6
#define PC_PORT    8884
7
#define MY_PORT    8884
8
9
volatile short int send_pkg = 0;
10
static struct udp_pcb *pic_rcv;
11
12
/*******************************************************************/
13
/* Try to receive a picture via UDP/IP */
14
/******************************************************************/
15
void udp_pic_rcv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port){
16
//if(p != NULL){
17
  printf("received my first packag!\n");
18
//      pbuf_free(p);
19
//}
20
}
21
/*************************************************************/
22
23
/*************************************************************/
24
int main()
25
{
26
27
...
28
send_pkg = 0
29
lwip_init();
30
...
31
32
33
   struct ip_addr rip;
34
   IP4_ADDR(&rip, 224,0,0,0);
35
36
pic_rcv = udp_new();
37
//udp_connect(pic_rcv, IPADDR_ANY, 63572);
38
udp_bind(pic_rcv, &rip, PC_PORT);
39
udp_recv(pic_rcv, udp_pic_rcv, NULL);
40
41
    //  This is the main loop for lwIP - other processing can be done by calling application functions.
42
    for(;;)
43
        {
44
      if(send_pkg == 1)
45
      {
46
        my_udp_send_from_ISR(pPicture, PIC_LENGTH);
47
        send_pkg = 0;
48
      }
49
50
        //  Process lwIP timer dependent code
51
        if( lwipProcessTimerFlag )
52
            lwipProcessTimers();
53
54
55
        //  Poll lwIP for incoming packets.
56
        ethernetif_input(&alteraTseNetif);
57
58
        }
59
60
    if(pPicture){
61
      free(pPicture);
62
      pPicture = NULL;
63
      printf("Buffer freed\n");
64
    }
65
    return 0;
66
}
67
/*********************************************************************/

Das Flag "send_pkg" wird in einer Timer-ISR auf 1 gesetzt um das senden 
anzustoßen.
Zum Testaufbau:
Auf einem dritten Rechner "C" erzeuge ich UDP-Pakete die ich gerne mit 
meinem TestBoard B empfangen würde, die Pakete werden an die 
Multicast-Addr. 224.0.0.0 Port 8884 gesendet. Ich sehe diese Pakete mit 
WireShark auf meinem Host-Rechner A, ebenso die gesendeten Pakete von 
meinem TestBoard B an die Multicast-Addr 192.168.1.255 Port 8884.

Aber ich kann mit meinem TestBoard B eben nicht die Pakete von C 
empfangen.

Vielen dank für die Hilfe

von Uwe B. (derexponent)


Lesenswert?

>Mein Problem liegt beim Empfangen von UDP-Pkgs

ja das hab ich schon verstanden
das dein senden funktioniert

ich hatte den gleichen Fehler
und es so gelöst wie beschrieben

lass mal alles so wie es jetzt ist
(also ohne das "udp_connect")

hat dein "Testboard-B" die IP "224.0.0.0" ?

falls ja, setz sie zum test mal in den gleichen Adressraum
wie den PC also z.B. auf "192.168.1.15"

und schreib ob es damit funktioniert

von Marius M. (marius1m)


Lesenswert?

Sorry,

also das Testboard B bekommt über DHCP die 192.168.1.106
PC A die 192.168.1.102  und
PC C die 192.168.1.103

ohne das udp_connect funktioniert es leider auch nicht. Ich habe eben im 
Debugger-Mode gesehen, dass die Multicast-Pakete an die Adresse 
224.0.0.0 empfangen werden und bis an die Funktion ip_input() 
weitergegeben werden.
Hier fällt das Paket glaube ich durch den Test auf
1
if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
2
         (ip_addr_ismulticast(&current_iphdr_src)))

Weiß du ob man in den lwipOpts.h irgendwo ein/ausschalten kann/muss 
Multicastpakete zu empfangen?

danke

von Uwe B. (derexponent)


Lesenswert?

>Weiß du ob man in den lwipOpts.h irgendwo ein/ausschalten kann/muss
>Multicastpakete zu empfangen?


nein, weiß ich leider nicht

...ich würde wie gesagt erst mal versuchen an
die "normale" IP zu senden also "192.168.1.106"
und schauen ob zumindest das geht

von Marius M. (marius1m)


Lesenswert?

ja das habe ich gerade getestet, bringt aber leider auch nicht den 
gewünschten Erfolg. Ich sehe das empfangene Paket aber das wird nicht 
mit meiner UDP-Callback-Funktion verknüpft. Scheint so als ob ich meinen 
udp-pcb nicht richtig aufsetzte...

von Godi S. (godi22)


Lesenswert?

Marius Mueller schrieb:
> Hi godi,
>
> hast du dein Problem lösen können? Ich habe das selbe Problem mit meinem
> lwip-Stack.

Hallo,

nein mein Problem mit UDP habe ich nicht mehr weiterverfolgt, da es mit 
TCP/IP funktioniert.
Wenn ich am Montag zeit finde dann kann ich ja noch mal was Probieren 
und die neu vorgeschlagenen Lösungen Probieren.

von Uwe B. (derexponent)


Lesenswert?

>Scheint so als ob ich meinen
>udp-pcb nicht richtig aufsetzte

hmm, komisch...ich mache genau das gleiche
1
struct udp_pcb *upcb_server;
2
struct ip_addr OwnIPaddr;
3
4
void init(void) {
5
  upcb_server = udp_new();
6
7
  IP4_ADDR( &OwnIPaddr, 192, 168, 0, 10 );
8
  udp_bind(upcb_server,&OwnIPaddr,65100);
9
  udp_recv(upcb_server, udp_receive_callback, NULL); 
10
}


damit funktioniert das senden und empfangen

wobei ich DHCP nicht aktiviert habe
(kann mir aber nicht vorstellen das es daran liegt)

Gruss Uwe

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.