1 2 3 4 5 6 7 | #define PF_NCSI 27 /* NCSI Address Family */ static struct net_proto_family ncsi_family_ops = { .family = PF_NCSI, .create = ncsi_create, .owner = THIS_MODULE, }; sock_register(&ncsi_family_ops); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | static struct proto_ops ncsi_ops = { .family = PF_NCSI, .owner = THIS_MODULE, .release = ncsi_release, .bind = sock_no_bind, .connect = sock_no_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = sock_no_getname, .poll = sock_no_poll, .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = ncsi_sendmsg, .recvmsg = ncsi_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; |
1 2 3 4 5 6 | #define NCSI_PROTOCOL 0x88F8 static struct packet_type ncsi_packet_type = { .type = __constant_htons(NCSI_PROTOCOL), .func = ncsi_rcv, }; dev_add_pack(&ncsi_packet_type); |
1 | #define AF_NCSI 27 /* NCSI 地址族定义 */ |
1 2 3 4 5 6 7 8 9 10 11 12 | /* NCSI 包头结构的定义 */ struct ncsihdr { unsigned char mc_id; unsigned char hdr_rev; unsigned char reserved0; unsigned char cmd_iid; unsigned char cmd; unsigned char chnl_id; unsigned short payload_len; unsigned int reserved2; unsigned int reserved3; }; |
1 2 3 4 5 6 7 8 9 10 11 | int OpenNCSISocket () { // 调用 socket 函数创建一个能够进行网络通信的套接字:协议族为 AF_NCSI,套接字类型为 SOCK_RAW sd = socket(AF_NCSI, SOCK_RAW, 0); if (sd < 0) { cout << "NCSI socket creation failed" << endl; return -1; } return sd; } |
1 2 3 4 5 | int CloseNCSISocket(int sd) { close(sd); // 调用 close 函数关闭已创建的套接字 return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | int SendRawNCSIPacket( int sd, // 已创建的 NCSI socket int Port_Num, //NCSI 命令发送到的以太网接口号 unsigned char cmd, //NCSI 命令号 unsigned char channel_id, // 承载 NCSI 命令的信道号 unsigned char *pu8Data, // 指向 NCSI 载荷的指针 unsigned short data_length//NCSI 载荷的长度 ) { int status; struct ncsihdr *ncsih; //NCSI 包头 struct iovec xmit_iovec[2]; // 创建 linux I/O 向量 iovec 结构数组 struct msghdr xmit_message; // 创建 linux 信息头 msghdr 结构数组 unsigned char pkt_buffer[60]; // 发送缓冲区 unsigned char *ncsi_payload ; //NCSI 载荷指针 // 封装以太网帧头 memset(pkt_buffer, 0, 60); memset(pkt_buffer, 0xff, 12); // 目的地址和源地址均为 0xFF FF FF FF FF FF pkt_buffer[12] = 0x88; pkt_buffer[13] = 0xf8; // 以太网帧头类型字段为 0x88f8,表示 NCSI 命令 // 封装 NCSI 包头 ncsih = (struct ncsihdr *) (pkt_buffer+14); ncsih->mc_id = 0x0; // 设置管理控制器 ID 为 0x0 ncsih->hdr_rev = 0x1; // 设置 NCSI 头版本号围 0x1 ncsih->cmd_iid = inciid(); // inciid() 是一个函数,用于获得当前发送数据包的 instance id ncsih->cmd = cmd; // 设置 NCSI 命令的命令号 ncsih->chnl_id = channel_id; // 设置 NCSI 命令传输的信道号 // 设置 NCSI 载荷的长度。由于网络字节序使用的都是大端模式,所以要调用 htons 进行相应的转换 ncsih->payload_len = htons(data_length); // 封装 NCSI 载荷 ncsi_payload = (unsigned char *)(pkt_buffer + 14 + sizeof(struct ncsihdr)); if ( (pu8Data!=NULL) && (data_length!=0) ) { memcpy(ncsi_payload, pu8Data, data_length); } // 封装 xmit_message xmit_message.msg_name = NULL; xmit_message.msg_namelen = 0; xmit_message.msg_iov = xmit_iovec; xmit_message.msg_iov[0].iov_base = (void *)&Port_Num; xmit_message.msg_iov[0].iov_len = sizeof(int); xmit_message.msg_iov[1].iov_base = (void *)pkt_buffer; xmit_message.msg_iov[1].iov_len = 60; xmit_message.msg_iovlen = 2; xmit_message.msg_control = NULL; xmit_message.msg_controllen = 0; xmit_message.msg_flags = 0; // 调用 linux 的 sendmsg 发送 NCSI 请求 status = sendmsg(sd, &xmit_message, 0); return status; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | int RecvRawNCSIPacket( int sd, // 已创建的 NCSI socket unsigned char *pu8NCSIpacket, // 用于存放接收数据的缓冲区 int buf_size, // 接收缓冲区的大小 int *Port_Num, // 接收 NCSI 响应的以太网接口号 int wait_time // 等待时间,单位毫秒 ) { int status; struct msghdr recv_message; // 创建 linux 信息头 msghdr 结构数组 struct iovec recv_iovec[3]; // 创建 linux I/O 向量 iovec 结构数组 if ( (NULL == pu8NCSIpacket) || (0 == buf_size ) return -1; // 封装 recv_message recv_message.msg_name = NULL; recv_message.msg_namelen = 0; recv_message.msg_iov = recv_iovec; recv_message.msg_iov[0].iov_base = (void *)&wait_time; recv_message.msg_iov[0].iov_len = sizeof(int); recv_message.msg_iov[1].iov_base = (void *) pu8NCSIpacket; recv_message.msg_iov[1].iov_len = buf_size; recv_message.msg_iov[2].iov_base = (void *)Port_Num; recv_message.msg_iov[2].iov_len = sizeof (int *); recv_message.msg_iovlen = 3; recv_message.msg_control = NULL; recv_message.msg_controllen = 0; recv_message.msg_flags = 0; // 调用 linux 的 recvmsg 接收 NCSI 响应 status = recvmsg(sd, &recv_message, 0); return status; } |
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |