#include #include #include #include #include #include #include #include struct traffic_mirror_ethdev_pkt_desc{}; struct traffic_mirror_ethdev_pkt_desc_pcap { unsigned int pktlen; char * pkt; }; static int pcap_ethdev_inject(struct traffic_mirror_ethdev * ethdev, const char * pkt, unsigned int pktlen) { return pcap_sendpacket(ethdev->pcap_device_handle, (const u_char *)pkt, pktlen); } static void pcap_ethdev_destroy(struct traffic_mirror_ethdev * ethdev) { pcap_close(ethdev->pcap_device_handle); return free(ethdev); } void traffic_mirror_ethdev_destroy(struct traffic_mirror_ethdev * ethdev) { ethdev->fn_destroy(ethdev); } int traffic_mirror_ethdev_inject(struct traffic_mirror_ethdev * ethdev, const char * pkt, unsigned int pktlen) { return ethdev->fn_inject(ethdev, pkt, pktlen); } struct traffic_mirror_ethdev * traffic_mirror_ethdev_pcap_create(const char * str_ethdev, void * logger) { struct traffic_mirror_ethdev * ethdev = ALLOC(struct traffic_mirror_ethdev, 1); char pcap_errbuf[PCAP_ERRBUF_SIZE] = {}; int fd = 0; struct ifreq if_req{}; ethdev->en_offload_ip_cksum = 0; ethdev->en_offload_tcp_cksum = 0; ethdev->en_offload_vlan = 0; /* open the device by pcap */ ethdev->pcap_device_handle = pcap_open_live(str_ethdev, 0, 0, 0, pcap_errbuf); if (!ethdev->pcap_device_handle) { TFE_LOG_ERROR(logger, "failed at pcap_open_live(), device = %s: %s", str_ethdev, pcap_errbuf); goto errout; } /* local ether address */ fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd < 0) { TFE_LOG_ERROR(logger, "failed at create socket: %s", strerror(errno)); goto errout; } memset(&if_req, 0, sizeof(if_req)); strncpy(if_req.ifr_ifrn.ifrn_name, str_ethdev, IFNAMSIZ - 1); if(ioctl(fd, SIOCGIFHWADDR, &if_req) < 0) { TFE_LOG_ERROR(logger, "failed at read hwaddr of device %s: %s", str_ethdev, strerror(errno)); goto errout; } for(int i = 0; i < 6; i++) { ethdev->local_ether_addr[i] = if_req.ifr_ifru.ifru_hwaddr.sa_data[i]; } /* MTU */ memset(&if_req, 0, sizeof(if_req)); strncpy(if_req.ifr_ifrn.ifrn_name, str_ethdev, IFNAMSIZ - 1); if (ioctl(fd, SIOCGIFMTU, &if_req) < 0) { TFE_LOG_ERROR(logger, "failed at read mtu of device %s: %s", str_ethdev, strerror(errno)); goto errout; } ethdev->mtu = if_req.ifr_ifru.ifru_mtu; strncpy(ethdev->str_device, str_ethdev, sizeof(ethdev->str_device) - 1); TFE_LOG_INFO(logger, "traffic mirror device %s (pcap mode): %02X:%02X:%02X:%02X:%02X:%02X, mtu=%u", ethdev->str_device, ethdev->local_ether_addr[0], ethdev->local_ether_addr[1], ethdev->local_ether_addr[2], ethdev->local_ether_addr[3], ethdev->local_ether_addr[4], ethdev->local_ether_addr[5], ethdev->mtu); ethdev->fn_inject = pcap_ethdev_inject; ethdev->fn_destroy = pcap_ethdev_destroy; close(fd); return ethdev; errout: if (fd > 0) close(fd); if (ethdev->pcap_device_handle) pcap_close(ethdev->pcap_device_handle); if (ethdev) FREE(ðdev); return nullptr; }