This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

problem in using Ethernet MULTICAST

hi,all:

I followed <TI81XX PSP ETHERNET Switch User Guide> to add multicast config but failed.

I need someone to confirm my step:

1 Configuring Kernel with VLAN Support;

2 Switch Config Commands  in the app source file.

include <stdio.h> ... include <linux/net_switch_config.h> int main(void) {
struct net_switch_config cmd_struct; struct ifreq ifr; int sockfd;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ); ifr.ifr_data = (char*)&cmd_struct; if
((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("Can't open the
socket\n"); return -1; } memset(&cmd_struct, 0, sizeof(struct
net_switch_config));
...//initialise cmd_struct with switch commands

cmd_struct.cmd = CONFIG_SWITCH_ADD_MULTICAST;
if (ioctl(sockfd, SIOCDEVPRIVATE, &ifr) < 0) { printf("Command failed\n"); close(sockfd); return -1; }
printf("command success\n"); close(sockfd); return 0; }

is that right? any step I miss?

thanks ahead of time.

Best Regards, 

qiuxicj

  • Hi Qiuxicj,

    qiuxicj MESSN said:
    I followed <TI81XX PSP ETHERNET Switch User Guide> to add multicast config but failed.

    What exactly do you mean here? Do you have the "Command failed" message?

    qiuxicj MESSN said:
    is that right? any step I miss?

    You can try to add few more lines of code.

    ...//initialise cmd_struct with switch commands

    cmd_struct.cmd = CONFIG_SWITCH_ADD_MULTICAST;

    cmd_struct.cmd_data.switchcmd.addr = <LLDP/Multicast Address>;    //unsigned char    addr[6];

    cmd_struct.cmd_data.switchcmd.mem_port = <port number>;  //0 or 1 or 2

    cmd_struct.cmd_data.switchcmd.vid = <VLAN ID>;   //VLAN identifier, range 0 to 4095

    cmd_struct.cmd_data.switchcmd.flag = <flag>; //0 or 1

    cmd_struct.cmd_data.switchcmd.untag_port = <untag port>;   //Multicast forward state, 0 to 3

    Does it make any difference now?

    BR

    Pavel

  • yes, I have the "command failed" message.

    thank you for your reply. I will try according to your instruction and answer to you next time.

    Best Regards,

    qiuxicj

  • hello, Pavel

    initialise cmd_struct with :

    cmd_struct.cmd = CONFIG_SWITCH_ADD_MULTICAST;

    cmd_struct.cmd_data.switchcmd.addr[0] = 230 ; 

    cmd_struct.cmd_data.switchcmd.addr[1] = 1 ; 

    cmd_struct.cmd_data.switchcmd.addr[2] = 1 ; 

    cmd_struct.cmd_data.switchcmd.addr[3] = 1 ; 

    cmd_struct.cmd_data.switchcmd.mem_port = 0;  //0 or 1 or 2

    cmd_struct.cmd_data.switchcmd.vid = 0;//VLAN identifier, range 0 to 4095

    cmd_struct.cmd_data.switchcmd.flag = 0; //0 or 1

    cmd_struct.cmd_data.switchcmd.untag_port = 0; //Multicast forward state, 0 to 3

    and the program run with the following message:

    Invalid switch config arguments!

    command failed!

    Is there any mistakes in my  code?

    Best Regards,

    qiuxicj

  • Qiuxicj,

    Please have a look on the below two files from the linux kernel:

    {EZSDK}/board-support/linux-2.6.37-psp04.04.00.01/drivers/net/cpsw.c

    {EZSDK}/board-support/linux-2.6.37-psp04.04.00.01/include/linux/etherdevice.h

    In cpsw.c we have:

    static int cpsw_switch_config_ioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
    {
        struct cpsw_priv *priv = netdev_priv(ndev);
        struct net_switch_config switch_config;
        int ret = -EFAULT;

        /*
        * Only SIOCDEVPRIVATE is used as cmd argument and hence, there is no
        * switch statement required.
        * Function calls are based on switch_config.cmd
        */
        if (cmd != SIOCDEVPRIVATE)
            return ret;

        if (copy_from_user(&switch_config,
                (struct net_switch_config *)(ifrq->ifr_data),
                sizeof(struct net_switch_config)))
            return ret;

        switch (switch_config.cmd) {
        case CONFIG_SWITCH_ADD_MULTICAST:
            if ((switchcmd(switch_config).untag_port <= 3) &&
                    (switchcmd(switch_config).vid <= 4095) &&
                    (switchcmd(switch_config).mem_port > 0) &&
                    (switchcmd(switch_config).mem_port <= 7) &&
                    is_multicast_ether_addr(
                    switchcmd(switch_config).addr)) {
                if (switchcmd(switch_config).vid == 0)
                    ret = cpsw_ale_add_mcast(priv->ale,
                        switchcmd(switch_config).addr,
                        switchcmd(switch_config).mem_port
                            << priv->host_port,
                        switchcmd(switch_config).flag,
                        switchcmd(switch_config).untag_port);
                else
                    ret = cpsw_ale_vlan_add_mcast(priv->ale,
                        switchcmd(switch_config).addr,
                        switchcmd(switch_config).mem_port
                            << priv->host_port,
                        switchcmd(switch_config).vid,
                        switchcmd(switch_config).flag,
                        switchcmd(switch_config).untag_port);
            } else {
                printk(KERN_ERR "Invalid Switch config arguments\n");
                ret = -EFAULT;
            }
            break;

        case CONFIG_SWITCH_ADD_UNICAST:

    .....

    }

    One of the conditions is that mem_port > 0, else we go in the "Invalid Switch config arguments" message. Can you try with cmd_struct.cmd_data.switchcmd.mem_port = 1, is there any difference?

    Also, have a look in the is_multicast_ether_addr(switchcmd(switch_config).addr) condition. is_multicast_ether_addr() function is described in etherdevice.h file:

    /**
     * is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
     * @addr: Pointer to a six-byte array containing the Ethernet address
     *
     * Return true if the address is a multicast address.
     * By definition the broadcast address is also a multicast address.
     */
    static inline int is_multicast_ether_addr(const u8 *addr)
    {
        return 0x01 & addr[0];
    }

    The only obligatory condition here is that addr[0] = 0x01, while you set it to 230 (0xE6). Can you double check your multicast ethernet address settings.

    I am also attaching sample code below, please examine:

    e2e.ti.com/cfs-file.ashx/__key/communityserver-discussions-components-files/118/5344.switch_2D00_config.tar.gz

    BR

    Pavel


  •  I have  try mem_port =1 ,but the result is failed. I will try your other suggestion.

    thank you for your detail reply.

    BR,

    qiuxicj

  • hello, Pavel

    recently, I am working on some other work. I will check the my multicast ethernet address settings when I have time and then I will tell you the result.

    but I can't access to the website:

    e2e.ti.com/cfs-file.ashx/__key/communityserver-discussions-components-files/118/5344.switch_2D00_config.tar.gz

    that you offer to me.

    BR,

    qiuxicj

  • Qiuxicj,

    I tried with "cmd_struct.cmd_data.switchcmd.addr[0] = 231;" and it works fine. But I am suspicious about this multicast IP address. We fill addr[0] to addr[3], but we actually have "unsigned char    addr[6];" defined in the net_switch_config.h file and net_switch_cmd structure. Please double check the example file : 7142.5344.switch-config.tar.gz

    int main(int argc, char **argv)
    {

    /* parse command line arguments */
        while ((c = getopt_long(argc, argv, options, long_options,
                &option_index)) != -1) {
            switch (c) {
                case '?':
                print_help();
                return 0;

            case 'm':
                SWITCH_CONFIG_COMMAND(cmd_struct.cmd,
                    CONFIG_SWITCH_ADD_MULTICAST);
                config_switch_str_to_ethaddr(optarg,
                    cmd_struct.cmd_data.switchcmd.addr);
            break;

    ....

     }

    /* String to Hex conversion */
    static unsigned char cpmac_str_to_hexnum(unsigned char c)
    {
        if(c >= '0' && c <= '9') return c - '0';
        if(c >= 'a' && c <= 'f') return c - 'a' + 10;
        if(c >= 'A' && c <= 'F') return c - 'A' + 10;
        return 0;
    }

    /* String to ethernet address conversion */
    static void config_switch_str_to_ethaddr(char *str, unsigned char *addr)
    {
        int i;
        unsigned char num;
        for(i = 0; i < 6; i++) {
            if((*str == '.') || (*str == ':')) str++;
            num = cpmac_str_to_hexnum(*str++) << 4;
            num |= (cpmac_str_to_hexnum(*str++));
            addr[i] = num;
        }
    }

  • Hi,

    Did you find a solution for this?

    I did the same thing, and found that the return error for the ioctl()  is 'EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ '

    Do you know how can I add a Multicast for the MAC? I need to allow income of certain network frames that pointing to specific MAC address.

    this is my code:

    			struct net_switch_config cmd_struct;
    			char addr_IEC61850[6] = {0x01, 0x0c, 0xcd, 0x01, 0x00, 0xaa};
    			struct ifreq ifr;
    			int sockfd;
    			int ret;
    			strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
    			ifr.ifr_data = (char*)&cmd_struct;
    			if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    				printf("Can't open the socket\n");
    				return -1;
    			}
    			memset(&cmd_struct, 0, sizeof(struct net_switch_config));
    
    			//initialise cmd_struct with switch commands
    			cmd_struct.cmd = CONFIG_SWITCH_ADD_MULTICAST;
    			cmd_struct.cmd_data.switchcmd.mem_port = 1;  //0 or 1 or 2
    			memcpy(cmd_struct.cmd_data.switchcmd.addr, addr_IEC61850, sizeof(addr_IEC61850));
    
    			if ((ret = ioctl(sockfd, SIOCDEVPRIVATE, &ifr)) < 0) {
    				printf("Command failed (%d) err %d (%s) \n", ret, errno, strerror(errno));
    				close(sockfd);
    				return -1;
    			}
    			printf("command success\n");
    			close(sockfd);
    			return 0;