Sending Ethernet 2 frames

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Sending Ethernet 2 frames

Jump to solution
5,555 Views
Cyanica
Contributor I

Hi,
 
Forgive me if I've missed the obvious but is it possible to send an ethernet type 2 frame from within the RTCS framework. ie I want to send data from one device to another device using just their MAC addresses.
 
Many thanks,
 
Richard
Labels (1)
Tags (1)
0 Kudos
1 Solution
2,543 Views
MichalP
NXP Employee
NXP Employee

Hi Richard,

 

To receive Ethernet frames with a specific Ether Type you have to register this protocol type on an Ethernet channel using the ENET_open function. Example:

 

if ((ENET_open((RTCS_get_enet_handle (MQX1588_ihandle)), 0x88F7, MQX1588_Recv_L2_1588, MQX1588_ihandle)) != ENET_OK)
{
       TGT_printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");
}

--------------------------------------------------

MQX1588_Recv_L2_1588 function then handles all received Eth. frames with 0x88F7 type.


As for sending, you have to create the frame (DST_MAC, SRC_MAC, EthType, Data) first, then create the pcb and finally use ENET_send_raw function for sending the packet. Example:

 

typedef struct {
      uint_8  DST[6];
     
uint_8  SRC[6];
      uint_8  ETHTYPE[2];
      uint_8  DATA[50];
} FRAME, * FRAME_PTR;

--------------------------------------

PCB_PTR     pcb_ptr;
uchar_ptr   mem_ptr;
FRAME_PTR   packet_ptr;


mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
if (mem_ptr==NULL) {
   return FALSE;
}
pcb_ptr = (PCB_PTR) mem_ptr;
packet_ptr = (FRAME_PTR)&mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
memcpy( phy_packet_ptr->DST
 [0], MY_FRAME, sizeof(MY_FRAME));

 

pcb_ptr->FREE = free_pcb;
pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;

if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(portHandle->device_number)), pcb_ptr)) == ENET_OK)
    return TRUE;
else
    return FALSE;
------------------------------------------

 

Regards

MichalP

View solution in original post

0 Kudos
13 Replies
2,544 Views
kfranz
Contributor III

Doing the ENET_join() should eliminate the need to use the "#define RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST 0".

This worked with MQX 4.2 on a Kinetis K64. For more information read about the following registers in the K64:

ENET_RCR bits PROM (promiscuous) and BC_REJ (broadcast), and ENET_GAUR, ENET_GALR.

0 Kudos
2,544 Views
kfranz
Contributor III

I have found that I also need to call ENET_join() after the ENET_open().

// destination MAC address

unsigned char aucDestMac[6] = {0x01,0x02,0x03,0x00,0x00,0x00};

ENET_join((RTCS_get_enet_handle(ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE))),

           0x88F7, // EtherType, ethernet type

           aucDestMac);

0 Kudos
2,544 Views
thiagow
Contributor III

I registered the function with ethertype 0x88f7  after I open a http server and now I sent a broadcast frame in another machine with these ethertype but the callback function never was called:

    if (ENET_open(RTCS_get_enet_handle(ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE)),

            0x88f7, recv_ethtype, ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE)) != MQX_OK)

        return 1;

void recv_ethtype

(

      PCB_PTR  pcb,

         /* [IN] the received packet */

      void    *handle

         /* [IN] the IP interface structure */

   )

{

   

    printf("\nreceived enet 0x88f7 frame\n");

}

I'm using the new MQX 4.1.1     and I can't see any error to register the ethertype but I never receive any frame.

Does anybody tested this code?  Is it work?

0 Kudos
2,544 Views
thiagow
Contributor III

I solved my problem enabling broadcasting setting 0 to RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST  on user_config.h:

#define RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST 0

0 Kudos
2,544 Views
MichalP
NXP Employee
NXP Employee

Hi Richard,

 

To receive Ethernet frames with a specific Ether Type you have to register this protocol type on an Ethernet channel using the ENET_open function. Example:

 

if ((ENET_open((RTCS_get_enet_handle (MQX1588_ihandle)), 0x88F7, MQX1588_Recv_L2_1588, MQX1588_ihandle)) != ENET_OK)
{
       TGT_printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");
}

--------------------------------------------------

MQX1588_Recv_L2_1588 function then handles all received Eth. frames with 0x88F7 type.


As for sending, you have to create the frame (DST_MAC, SRC_MAC, EthType, Data) first, then create the pcb and finally use ENET_send_raw function for sending the packet. Example:

 

typedef struct {
      uint_8  DST[6];
     
uint_8  SRC[6];
      uint_8  ETHTYPE[2];
      uint_8  DATA[50];
} FRAME, * FRAME_PTR;

--------------------------------------

PCB_PTR     pcb_ptr;
uchar_ptr   mem_ptr;
FRAME_PTR   packet_ptr;


mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
if (mem_ptr==NULL) {
   return FALSE;
}
pcb_ptr = (PCB_PTR) mem_ptr;
packet_ptr = (FRAME_PTR)&mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
memcpy( phy_packet_ptr->DST
 [0], MY_FRAME, sizeof(MY_FRAME));

 

pcb_ptr->FREE = free_pcb;
pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;

if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(portHandle->device_number)), pcb_ptr)) == ENET_OK)
    return TRUE;
else
    return FALSE;
------------------------------------------

 

Regards

MichalP

0 Kudos
2,544 Views
danielarenas
Contributor I

     Hi Michal:

I'm trying to debug this code at the TWR MCF51CN128 KIT, but codewarrior don't recognize the functions and parameters like RTCS_get_enet_handle and MQX1588_ihandle, I don't know if I'm missing something.

Thanks,

Daniel.

0 Kudos
2,544 Views
MichalP
NXP Employee
NXP Employee

Hello Daniel,

RTCS_get_enet_handle should be accessible from the application, do not forget to include path to the compiled RTCS library (<MQX installation folder>\lib\<board>\<target>\rtcs\rtcs.a) and to include the "rtcs.h" into you code. As for the MQX1588_ihandle variable this is just an example from an application. You can get the ihandle by calling ipcfg_get_ihandle(ENET_DEVICE) so for registering the protocol type you can call:

if ((ENET_open((RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE))), 0x88F7, MQX1588_Recv_L2_1588, NULL)) != ENET_OK)

{

  printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");

}

see <MQX installation folder>\mqx\source\io\enet\enopen.c for description of ENET_open function and it's parameters.

Regards

MichalP


0 Kudos
2,544 Views
danielarenas
Contributor I

Hi Michal:

I have done what you adviced me to  "see <MQX installation folder>\mqx\source\io\enet\enopen.c for description of ENET_open function and it's parameters."

I know that “ENET_open” Registers a protocol type on an Ethernet channel.

and the structure is like this:

uint_32 ENET_open

   (

      /* [IN] the Ethernet state structure */

      _enet_handle handle,

      /* [IN] the protocol */

      uint_16 type,

      /* [IN] the callback function */

      void (_CODE_PTR_ service)(PCB_PTR, pointer),

      /* [IN] private data for the callback */

      pointer private

   )

I don´t know how to use the callback function and also the private data for the callback??

I also found this function ENET_send for send a packet and this is the structure of it:

uint_32 ENET_send

   (

      /* [IN] the Ethernet state structure */

      _enet_handle   handle,

      /* [IN] the packet to send */

      PCB_PTR packet,

      /* [IN] the protocol */

      uint_16 type,

      /* [IN] the destination Ethernet address */

      _enet_address  dest,

      /* [IN] optional flags, zero = default */

      uint_32 flags

   )

I don´t know if this is the same function that you use call "ENET_send_raw"?

Im still having troubles trying to understand this functions…

Thanks,

  1. Daniel.
0 Kudos
2,544 Views
MichalP
NXP Employee
NXP Employee

Hello Daniel,

let's consider we have registered 0x88F7 protocol type on an Ethernet channel by:

ENET_open((RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE))), 0x88F7, MQX1588_Recv_L2_1588, enet_ptr)

where enet_ptr of ENET_CONTEXT_STRUCT_PTR type is the requested private data to be passsed to the MQX1588_Recv_L2_1588 callback function.

Then the callback function should look like this:

void MQX1588_Recv_L2_1588

   (

      PCB_PTR  pcb, /* [IN] the received packet */

      pointer  private  /* [IN] pointer to private data */

   )

{

    ENET_CONTEXT_STRUCT_PTR enet_ptr = (ENET_CONTEXT_STRUCT_PTR) private;

    MACNET_CONTEXT_STRUCT_PTR  macnet_context_ptr = (MACNET_CONTEXT_STRUCT_PTR)enet_ptr->MAC_CONTEXT_PTR;

    /* Now you have the pointer to the Ethernet packet in pcb->FRAG[0].FRAGMENT

       and the buffer length in pcb->FRAG[0].LENGTH) */

    /* Do not forget to free the memory after the packet payload is read or passed to another user buffer */

    PCB_free(pcb);

}

As for functions for sending, use the ENET_send_raw function for sending data from one device to another device using just their MAC addresses - that's what's discuseed in this thread. You can find how to do it from previous items of this thread.

Regards

MichalP

0 Kudos
2,544 Views
kroumkouzmanov
Contributor I

Hello Michal,

I am using your code above to send an Ethernet frame but I get an error on the line: pcb_ptr->FREE = free_pcb; (undefined indentifier free_pcb). When I remove this line I am able to send the frame but after that the program stops after printing

pNET

Here is my actual code:

mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
     
      pcb_ptr = (PCB_PTR) mem_ptr;
      packet_ptr = (FRAME_PTR) & mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
      memcpy( packet_ptr, gs_buf, sizeof(gs_buf));

      pcb_ptr->FREE = free_pcb;
      pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
      pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;
        
      if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE)), pcb_ptr)) != ENET_OK)
      printf("ENET Error\n");
      else
      printf("pNET Sent\n");

I am working with MQX 3.8.1 and CW10.3 and I can not identify the name of the function I need to use in pcb_ptr->FREE =

Could you please point out to the right function

Thank you, Kroum

0 Kudos
2,543 Views
firebrizz
Contributor II

free_pcb it is a function which frees the memory after the packet is sent by ENET, something like this:


void free_pcb

   (

         /* [IN] the PCB to enqueue */

      PCB_PTR  pcb_ptr

   )

{

     _mem_free(pcb_ptr);

}

0 Kudos
2,543 Views
kroumkouzmanov
Contributor I

Thank you, Fire Brizz! I got it working.

Kroum

0 Kudos
2,543 Views
DougMS
Contributor I

Did you get this working? I have having the same problem.

0 Kudos