summaryrefslogtreecommitdiff
path: root/src/extensions/inline_keepalive.cpp
diff options
context:
space:
mode:
author杨威 <[email protected]>2023-06-20 15:32:46 +0800
committer杨威 <[email protected]>2023-06-26 20:18:26 +0800
commitacc0ee76193f032c64dca379acad9c7256d6e13f (patch)
treef0f7128a993710dbeca21f4fc97184fb85345e19 /src/extensions/inline_keepalive.cpp
parent7510b7b17e9494550076d3da6116526282140b44 (diff)
🌈 style(inner_plug): 目录更名为extensions
Diffstat (limited to 'src/extensions/inline_keepalive.cpp')
-rw-r--r--src/extensions/inline_keepalive.cpp908
1 files changed, 908 insertions, 0 deletions
diff --git a/src/extensions/inline_keepalive.cpp b/src/extensions/inline_keepalive.cpp
new file mode 100644
index 0000000..3859443
--- /dev/null
+++ b/src/extensions/inline_keepalive.cpp
@@ -0,0 +1,908 @@
+
+/*
+ ��WY��Ŀ��������, �Ƿ���GDEV�����Ǹ��ݲ��������״̬��̬����, �������ٹ̶�һֱ����,
+
+ ���Խ�GDEV-KEEPALIVE���ܴ�ƽ̨�а���,
+ ���ص�IP��UDP�������ԭ�б����.
+
+ Ŀǰû��arp_entry, ethernet_entry, ARP�ظ�������ʱ������ƽ̨�ڲ�.
+*/
+
+#include <pthread.h>
+#ifndef __FAVOR_BSD
+#define __FAVOR_BSD 1
+#endif
+
+#include "sapp_api.h"
+#include "sapp_private_api.h"
+#include "sapp_declaration.h"
+#include "stream_inc/gdev_keepalive.h"
+#include "field_stat2.h"
+
+#if IOMODE_MARSIO
+static struct mr_instance * gdev_plug_extern_marsio4_instance; /* dlopen dynamic link sapp->marsio4 instance */
+extern int marsio_send_burst_with_options_for_tcpdumpmesa(struct mr_sendpath * sendpath, queue_id_t sid, marsio_buff_t * mbufs[], int nr_mbufs, uint16_t options);
+extern int (*ptr_marsio_buff_malloc_global)(struct mr_instance * instance, marsio_buff_t *marsio_buff[], unsigned int nr_mbufs, int socket_id, int thread_id);
+extern char * (*ptr_marsio_buff_append)(marsio_buff_t *m, uint16_t len);
+extern void (*ptr_marsio_buff_free)(struct mr_instance * instance, marsio_buff_t *marsio_buff[],unsigned int nr_mbufs, int socket_id, int thread_id);
+#endif
+
+#define MAX_SUPPORT_GDEV_NUM (64) /* ÿ���߳������֧��inline device������, ���ݷ������Ժ��߳����IJ�ͬ, ��Сֵ��MAX_SUPPORT_GDEV_NUM, ���ֵ��MAX_SUPPORT_GDEV_NUM * sapp_thread_count */
+#define MAX_VXLAN_SERVICE_NUM (256) /* Ŀǰ���֧��255�ֲ�ͬҵ��, �����±������255 */
+
+#define MAX_NO_PKT_TIMEOUT (120) /* ������ô��ʱ��һֱû�����, �Ѵ��豸�޳� */
+
+static void *gdev_kp_log_handle;
+enum prog_work_mode_t{
+ PROG_MODE_MASTER = 1,
+ PROG_MODE_SLAVE = 2,
+};
+
+
+enum gdev_keepalive_fs2_column_t{
+ FS2_COLUMN_REQUEST_NUM = 0,
+ FS2_COLUMN_REPLY_NUM,
+ __FS2_COLUMN_MAX,
+};
+
+static int gdev_keepalive_fs2_column_id_array[__FS2_COLUMN_MAX];
+
+/*
+ ÿ���߳�, ÿ��Inline-DEV-IP, ÿ��ҵ��ֱ�ͳ��.
+*/
+
+typedef struct {
+ int gdev_keepalive_type; /* for example: GDEV_KEEPALIVE_TYPE_BFD */
+ //int gdev_keepalive_service_num;
+ unsigned int keepalive_request_num; /* ��ǰҵ�񱣻����������, ÿ��һ��ʱ������ */
+ unsigned int keepalive_reply_num; /* ��ǰҵ�񱣻�Ӧ�������, ����service��ͬ, ����ijЩҵ����ⲻ�ظ�Ӧ��, ����request����һ������reply */
+ int field_stat_line_id; /* fs2 �������id */
+ time_t last_time; /* ��ǰҵ�����һ���յ��������ʱ�� */
+}gdev_keepalive_status_per_service_t;
+
+
+typedef struct{
+ int inuse_flag; /* ��λ�ñ�ռ�� */
+ unsigned int gdev_ip_network_order;
+ unsigned int keepalive_request_num; /* ��ǰ�豸�������������, ÿ��һ��ʱ������ */
+ unsigned int keepalive_reply_num; /* ��ǰ�豸����Ӧ�������, ����service��ͬ, ����ijЩҵ����ⲻ�ظ�Ӧ��, ����request����һ������reply */
+ int fs2_line_id;
+ time_t last_time; /* ��ǰ�豸���һ���յ��������ʱ�� */
+ gdev_keepalive_status_per_service_t service_array[MAX_VXLAN_SERVICE_NUM]; /* ��BFDЭ���������service, ICMPĬ�϶���0��ҵ�� */
+}gdev_keepalive_status_per_dev_t;
+
+
+
+struct _gdev_keepalive_status_per_thread{
+ gdev_keepalive_status_per_dev_t gdev_array[MAX_SUPPORT_GDEV_NUM];
+}__attribute__ ((aligned (64)));
+
+typedef struct _gdev_keepalive_status_per_thread gdev_keepalive_status_per_thread_t;
+
+
+/*
+ ˵��: gdev�ı���״̬����һ����������, ��Ϊ���Ȳ�֪������,
+
+ ��Ϊʲô����hash? ����? ��̬����?
+
+ ����ģʽ�Ƕ���߳�д, һ���̶߳�ȡ���������, ����Ƕ�̬�����ݽṹ, �ⲻ��Ҫ����,
+ ʹ���������ȷ��������ڴ�, ����־λinuse_flag��ʾ�Ƿ���ʹ��, ��֤��д����ͻ.
+*/
+static gdev_keepalive_status_per_thread_t GDEV_KEEPALIVE_STAT[MAX_THREAD_NUM];
+
+static volatile int g_dev_keepalive_flag = 1; /* ȫ�ֱ����־, ���в���������������Ҫ������������ */
+
+
+static volatile struct gdev_keepalive_service_ctrl g_dev_keepalive_service_ctrl_array[MAX_VXLAN_SERVICE_NUM];/* ����ij��ҵ����Ƿ񱣻� */
+
+//extern int g_packet_io_thread_num;
+//extern time_t g_CurrentTime;
+static int g_dev_keepalive_default_action = 1; /* ����g_dev_keepalive_service_ctrl_array��û�е�ҵ���, �DZ���Dz����� */
+static unsigned int sendto_gdev_card_ip; /* ��Gdev����������IP��ַ, ������, network-order */
+extern int sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, u_int16_t sum,
+ u_int16_t id, u_int16_t seq, u_int8_t *payload, u_int32_t payload_s, unsigned char *buf);
+extern char *timet_to_str(time_t timet, char *time_str, int time_str_len);
+static int vxlan_sport_service_map_init(void);
+extern void del_last_rn(char *data, int max_len);
+static unsigned char g_vxlan_sport_to_service_id[65536]; /* �����±�ΪԴ�˿�, ֵΪservice-id, �������ֵ��65535 */
+
+
+static int gdev_kp_action_judge(int service_id)
+{
+ if(0 == g_dev_keepalive_flag){
+ return 0;
+ }
+
+ return g_dev_keepalive_service_ctrl_array[service_id].keepalive_switch;
+}
+
+
+/*
+ prometheus fs2 line���Ʋ��ܰ�����Щ�ַ�:
+ const char* reserverd="|:\n\r. \t<>[]#!@";
+
+ ����ip��ַ�ķָ�����Ҫ�ij�'_'
+*/
+static const char *fs2_inet_ntop(unsigned int gip_net, char *buf, int buf_len)
+{
+ const unsigned char *ip_char_array = (unsigned char *)&gip_net;
+
+ snprintf(buf, buf_len, "%u_%u_%u_%u", ip_char_array[0], ip_char_array[1],ip_char_array[2], ip_char_array[3]);
+
+ return buf;
+}
+
+
+static void gdev_keepalive_stat_update(int tid, unsigned int gip_net, int type, int service_id, int action)
+{
+ gdev_keepalive_status_per_thread_t *cur_thread_stat = &GDEV_KEEPALIVE_STAT[tid];
+ int bingo = 0, index;
+
+ for(index = 0; index < MAX_SUPPORT_GDEV_NUM; index++){
+ if((1 == cur_thread_stat->gdev_array[index].inuse_flag)
+ && (gip_net == cur_thread_stat->gdev_array[index].gdev_ip_network_order)){
+ bingo = 1;
+ break;
+ }
+ }
+
+ /* not found this inline device */
+ if(0 == bingo){
+ /* search a empty place */
+ for(index = 0; index < MAX_SUPPORT_GDEV_NUM; index++){
+ if(0 == cur_thread_stat->gdev_array[index].inuse_flag){
+ cur_thread_stat->gdev_array[index].inuse_flag = 1;
+ break;
+ }
+ }
+
+ if(index >= MAX_SUPPORT_GDEV_NUM){
+ MESA_handle_runtime_log(gdev_kp_log_handle, RLOG_LV_FATAL, "[gdev_keepalive]",
+ "Too many inline devices, max support: %d!\n", MAX_SUPPORT_GDEV_NUM);
+ return;
+ }
+
+ }
+
+ if(service_id < 0 || service_id >= MAX_VXLAN_SERVICE_NUM){
+ MESA_handle_runtime_log(gdev_kp_log_handle, RLOG_LV_INFO, "[gdev_keepalive]",
+ "invalid service num: %d!\n", service_id);
+ return;
+ }
+
+ /* update this device */
+ cur_thread_stat->gdev_array[index].inuse_flag = 1;
+ cur_thread_stat->gdev_array[index].gdev_ip_network_order = gip_net;
+ cur_thread_stat->gdev_array[index].last_time = g_CurrentTime;
+ cur_thread_stat->gdev_array[index].keepalive_request_num++;
+ cur_thread_stat->gdev_array[index].keepalive_reply_num++;
+
+ /* update by service */
+ cur_thread_stat->gdev_array[index].service_array[service_id].gdev_keepalive_type = type;
+ cur_thread_stat->gdev_array[index].service_array[service_id].keepalive_request_num++;
+ if(action){
+ cur_thread_stat->gdev_array[index].service_array[service_id].keepalive_reply_num++;
+ }
+ cur_thread_stat->gdev_array[index].service_array[service_id].last_time = g_CurrentTime;
+
+ return;
+}
+
+/* �����豸�������BFDЭ�� */
+static int gdev_keepalive_bfd_plug(const raw_pkt_t *raw_pkt, int thread_id, unsigned char dir, unsigned char *send_buf)
+{
+ char payload_buf[1472];
+ struct mesa_ethernet_hdr *raw_eth_hdr = (struct mesa_ethernet_hdr *)raw_pkt->raw_pkt_data;
+ struct mesa_ip4_hdr *ip_hdr = (struct mesa_ip4_hdr *)((char *)raw_eth_hdr+ SENDPACKET_ETH_H);
+ struct mesa_udp_hdr *udp_hdr = (struct mesa_udp_hdr *)((char *)raw_eth_hdr + SENDPACKET_ETH_H + ip_hdr->ip_hl*4);
+ bfd_header_t *bfd_net_hdr = (bfd_header_t *)((char *)raw_eth_hdr + SENDPACKET_ETH_H + ip_hdr->ip_hl*4 + SENDPACKET_UDP_H);
+ bfd_header_t *bfd_send_hdr = (bfd_header_t *)payload_buf;
+ char bfd_buf[4];
+ int payload_len = ntohs(udp_hdr->uh_ulen) - SENDPACKET_UDP_H;
+ int service_id = 0;
+ int action;
+
+ service_id = vxlan_sport_map_to_service_id(ntohs(udp_hdr->uh_sport));
+ action = gdev_kp_action_judge(service_id);
+
+ /* ��ʹaction=0, stat_updateҲҪ����, ��Ҫͳ�Ʋ��ظ������ҵ����Ϣ */
+ gdev_keepalive_stat_update(thread_id, ip_hdr->ip_src.s_addr, GDEV_KEEPALIVE_TYPE_BFD, service_id, action);
+ if(0 == action){
+ return -1;
+ }
+
+ /* ��ȡ����service_id, ����Ӧ�ûظ�����Ӧ��, go on !! */
+
+ memcpy(payload_buf, bfd_net_hdr, payload_len);
+
+ // passive bfdd, DOWN->INIT, UP->UP
+ if (bfd_send_hdr->state == BFD_MSG_FLAGS_DOWN)
+ {
+ //DOWN->INIT
+ bfd_send_hdr->state = BFD_MSG_FLAGS_INIT;
+ // set keep_alive ip as discriminator
+ // memcpy(bfd_send_hdr->your_discriminator, &ip_hdr->ip_dst.s_addr, 4);
+ }
+ // swap discriminator
+ memcpy(bfd_buf, bfd_send_hdr->my_discriminator, 4);
+ memcpy(bfd_send_hdr->my_discriminator, bfd_send_hdr->your_discriminator, 4);
+ memcpy(bfd_send_hdr->your_discriminator, bfd_buf, 4);
+
+ sendpacket_build_ethernet(raw_eth_hdr->ether_shost, raw_eth_hdr->ether_dhost, ETH_P_IP, NULL, 0, send_buf);
+
+ sendpacket_build_udp_dual_stack(ntohs(udp_hdr->uh_sport), /* BFDЭ�鲻����Դ��Ŀ�Ķ˿� */
+ ntohs(udp_hdr->uh_dport),
+ (char *)bfd_send_hdr,
+ payload_len,
+ payload_len,
+ send_buf + SENDPACKET_ETH_H + SENDPACKET_IP_H);
+
+ sendpacket_build_ipv4(SENDPACKET_UDP_H + payload_len,
+ 0,
+ ntohs(ip_hdr->ip_id),
+ ntohs(ip_hdr->ip_off),
+ ip_hdr->ip_ttl,
+ IPPROTO_UDP,
+ ip_hdr->ip_dst.s_addr,
+ ip_hdr->ip_src.s_addr, /* ����Դ��Ŀ��IP��ַ */
+ NULL, 0,
+ send_buf + SENDPACKET_ETH_H);
+
+ sendpacket_do_checksum(send_buf + SENDPACKET_ETH_H,
+ IPPROTO_IP,
+ SENDPACKET_IP_H);
+
+ sendpacket_do_checksum(send_buf + SENDPACKET_ETH_H,
+ IPPROTO_UDP,
+ payload_len + SENDPACKET_UDP_H);
+
+ return SENDPACKET_IP_H + SENDPACKET_UDP_H+sizeof(bfd_header_t) + sizeof(struct mesa_ethernet_hdr);
+}
+
+/* �����豸�������BFDЭ�� */
+static int gdev_keepalive_icmp_plug(const raw_pkt_t *raw_pkt, int thread_id, unsigned char dir, unsigned char *send_buf)
+{
+ struct mesa_ethernet_hdr *raw_eth_hdr = (struct mesa_ethernet_hdr *)raw_pkt->raw_pkt_data;
+ struct mesa_ip4_hdr *ip_hdr = (struct mesa_ip4_hdr *)((char *)raw_eth_hdr + SENDPACKET_ETH_H);
+ struct mesa_icmp_echo_hdr *icmp_hdr = (struct mesa_icmp_echo_hdr *)((char *)raw_eth_hdr + SENDPACKET_ETH_H + ip_hdr->ip_hl*4);
+ unsigned char *icmp_payload;
+ int icmp_payload_len;
+
+ gdev_keepalive_stat_update(thread_id, ip_hdr->ip_src.s_addr, GDEV_KEEPALIVE_TYPE_ICMP, 0, g_dev_keepalive_default_action);
+
+ icmp_payload = (unsigned char *)icmp_hdr + sizeof(struct mesa_icmp_echo_hdr);
+ icmp_payload_len = ntohs(ip_hdr->ip_len) - ip_hdr->ip_hl*4 - sizeof(struct mesa_icmp_echo_hdr);
+
+ sendpacket_build_ethernet(raw_eth_hdr->ether_shost, raw_eth_hdr->ether_dhost, ETH_P_IP, NULL, 0, send_buf);
+
+ sendpacket_build_icmpv4_echo(ICMP_ECHOREPLY, 0, 0,
+ ntohs(icmp_hdr->icd_id),
+ ntohs(icmp_hdr->icd_seq),
+ icmp_payload,
+ icmp_payload_len,
+ send_buf + SENDPACKET_ETH_H + SENDPACKET_IP_H);
+
+ sendpacket_build_ipv4(icmp_payload_len + sizeof(struct mesa_icmp_echo_hdr),
+ 0, 0x1234, 0, 64, IPPROTO_ICMP,
+ ip_hdr->ip_dst.s_addr,
+ ip_hdr->ip_src.s_addr,
+ NULL, 0,
+ send_buf + SENDPACKET_ETH_H);
+ memcpy(send_buf + SENDPACKET_ETH_H + SENDPACKET_IP_H + sizeof(struct mesa_icmp_echo_hdr),
+ icmp_payload,
+ icmp_payload_len);
+
+ sendpacket_do_checksum(send_buf + SENDPACKET_ETH_H,
+ IPPROTO_IP,
+ SENDPACKET_IP_H);
+
+ sendpacket_do_checksum(send_buf + SENDPACKET_ETH_H,
+ IPPROTO_ICMP,
+ icmp_payload_len + sizeof(struct mesa_icmp_echo_hdr));
+
+ return ntohs(ip_hdr->ip_len) + sizeof(struct mesa_ethernet_hdr);
+}
+
+
+static int gdev_keepalive_plug(const raw_pkt_t *raw_pkt, int thread_id, unsigned char dir, int keepalive_type)
+{
+ int ret = -1, send_len;
+ MESA_send_handle *snd_handle = NULL;
+#if IOMODE_MARSIO
+ const struct mesa_ethernet_hdr *raw_eth_hdr = (struct mesa_ethernet_hdr *)raw_pkt->raw_pkt_data;
+ struct mesa_ethernet_hdr *snd_eth_hdr;
+#endif
+
+ snd_handle = packet_io_get_send_handle(thread_id);
+ if(NULL == snd_handle){
+ return -1;
+ }
+ snd_handle->send_buf = packet_io_get_sendbuf(SEND_TYPE_LINK_INJECT, thread_id);
+ if(NULL == snd_handle->send_buf){
+ return 0;
+ }
+
+ switch(keepalive_type){
+ case GDEV_KEEPALIVE_TYPE_BFD:
+ send_len = gdev_keepalive_bfd_plug(raw_pkt, thread_id, dir, snd_handle->send_buf);
+ if(send_len < 0){
+ goto err;
+ }
+ break;
+
+ case GDEV_KEEPALIVE_TYPE_ICMP:
+ send_len = gdev_keepalive_icmp_plug(raw_pkt, thread_id, dir, snd_handle->send_buf);
+ if(send_len < 0){
+ goto err;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+
+ ret = packet_io_send(snd_handle, send_len, SEND_TYPE_LINK_INJECT,
+ __ADDR_TYPE_IP_PAIR_V4, dir, thread_id,
+ (char *)KILL_TCP_PHONY_POINTER, (int *)KILL_TCP_PHONY_POINTER, raw_pkt);
+
+ packet_io_free_sendbuf(SEND_TYPE_LINK_INJECT, thread_id);
+ return ret;
+
+err:
+ packet_io_free_sendbuf(SEND_TYPE_LINK_INJECT, thread_id);
+ return -1;
+}
+
+/* �ڴ���UDP����, ����ʶ����Щ������BFD����� */
+static inline int gdev_bfd_pkt_identify(const struct streaminfo *a_udp)
+{
+ if(g_topology_mode != NET_CONN_SERIAL_GDEV){ /* ��G����ģʽ */
+ return 0;
+ }
+
+ if((sendto_gdev_card_ip != a_udp->addr.tuple4_v4->daddr)
+ && (sendto_gdev_card_ip != a_udp->addr.tuple4_v4->saddr)){
+ return 0;
+ }
+
+ if(BFD_DEFAULT_PORT != ntohs(a_udp->addr.tuple4_v4->dest)){
+ return 0;
+ }
+
+ if(ADDR_TYPE_IPV4 != a_udp->addr.addrtype){ /* Ŀǰ������IPv4 */
+ return 0;
+ }
+
+ if(a_udp->pudpdetail->datalen != (int)sizeof(bfd_header_t)){
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static long _gdev_keepalive_rcv_pps;
+static long _gdev_keepalive_snd_pps;
+
+static void __gdev_keepalive_pkt_calc_pps(void)
+{
+ static long _last_rcv_num, _last_snd_num;
+ long rcv_sum = 0;
+ long snd_sum = 0;
+ int tid, dev_num;
+
+ for(tid = 0; tid < g_packet_io_thread_num; tid++){
+ for(dev_num = 0; dev_num < MAX_SUPPORT_GDEV_NUM; dev_num++){
+ if(GDEV_KEEPALIVE_STAT[tid].gdev_array[dev_num].inuse_flag != 0){
+ rcv_sum += GDEV_KEEPALIVE_STAT[tid].gdev_array[dev_num].keepalive_request_num;
+ snd_sum += GDEV_KEEPALIVE_STAT[tid].gdev_array[dev_num].keepalive_reply_num;
+ }
+ }
+ }
+
+ _gdev_keepalive_rcv_pps = rcv_sum - _last_rcv_num;
+ _gdev_keepalive_snd_pps = snd_sum - _last_snd_num;
+
+ _last_rcv_num = rcv_sum;
+ _last_snd_num = snd_sum;
+
+ return;
+}
+
+
+static void gdev_keepalive_update_local_log(void)
+{
+ FILE *gdev_status_fp;
+ int dev_index, thread_seq, service_index;
+ int platform_thread_num;
+ char cur_time_str[64];
+ char tmp_ip_str[INET6_ADDRSTRLEN];
+ const char *tmp_keealive_type;
+ const gdev_keepalive_status_per_thread_t *this_thread_stat;
+ const gdev_keepalive_status_per_dev_t *this_dev_stat;
+
+ gdev_status_fp = fopen(ABBR_INLINE_KEEPALIVE_LOG_DATA_FILE, "w+");
+ if(NULL == gdev_status_fp){
+ return;
+ }
+
+ platform_thread_num = get_thread_count();
+ timet_to_str(time(NULL), cur_time_str, 64);
+ fprintf(gdev_status_fp, "%-20s %-16s %-11s %-5s %-5s %-16s %-16s\n",
+ "Last-update-time", "Gdev-ip", "Service-Num", "Ctrl", "Type", "Rcv-pkt", "Snd-pkt");
+
+ for(thread_seq = 0; thread_seq < platform_thread_num; thread_seq++)
+ {
+ this_thread_stat = &GDEV_KEEPALIVE_STAT[thread_seq];
+
+ for(dev_index = 0; dev_index < MAX_SUPPORT_GDEV_NUM; dev_index++){
+ if(0 == this_thread_stat->gdev_array[dev_index].inuse_flag){
+ continue;
+ }
+
+ this_dev_stat = &this_thread_stat->gdev_array[dev_index];
+ inet_ntop(AF_INET, &this_dev_stat->gdev_ip_network_order, tmp_ip_str, sizeof(tmp_ip_str));
+
+ for(service_index = 0; service_index < MAX_VXLAN_SERVICE_NUM; service_index++){
+ if(this_dev_stat->service_array[service_index].keepalive_request_num > 0){
+ if(GDEV_KEEPALIVE_TYPE_ICMP == this_dev_stat->service_array[service_index].gdev_keepalive_type){
+ tmp_keealive_type = "ICMP";
+ }else if(GDEV_KEEPALIVE_TYPE_BFD == this_dev_stat->service_array[service_index].gdev_keepalive_type){
+ tmp_keealive_type = "BFD";
+ }else{
+ tmp_keealive_type = "Unknown";
+ }
+
+
+ fprintf(gdev_status_fp, "%-20s %-16s %-11d %-5d %-5s %-16u %-16u\n",
+ cur_time_str,
+ tmp_ip_str,
+ service_index,
+ gdev_kp_action_judge(service_index),
+ tmp_keealive_type,
+ this_dev_stat->service_array[service_index].keepalive_request_num,
+ this_dev_stat->service_array[service_index].keepalive_reply_num);
+ }
+ }
+
+ }
+ }
+
+ fclose(gdev_status_fp);
+
+}
+
+
+static void gdev_keepalive_clear_stat(void)
+{
+ int platform_thread_num, dev_index, thread_seq, service_index;
+ gdev_keepalive_status_per_thread_t *this_thread_stat;
+ gdev_keepalive_status_per_dev_t *this_dev_stat;
+
+ platform_thread_num = get_thread_count();
+ for(thread_seq = 0; thread_seq < platform_thread_num; thread_seq++){
+ this_thread_stat = &GDEV_KEEPALIVE_STAT[thread_seq];
+
+ for(dev_index = 0; dev_index < MAX_SUPPORT_GDEV_NUM; dev_index++){
+ if(0 == this_thread_stat->gdev_array[dev_index].inuse_flag){
+ continue;
+ }
+
+ this_dev_stat = &this_thread_stat->gdev_array[dev_index];
+
+ this_dev_stat->keepalive_request_num = 0;
+ this_dev_stat->keepalive_reply_num = 0;
+
+#if 0 /* �Ȳ�֧����̭, ��Ϊ��ǰ�豸��line_id�Ѿ�ע�ᵽfs2, ����ʹ�õĻ�, name�޷����� */
+ if(this_dev_stat->last_time + MAX_NO_PKT_TIMEOUT < g_CurrentTime){
+ char dev_ip_str[INET6_ADDRSTRLEN];
+ this_dev_stat->inuse_flag = 0;
+ inet_ntop(AF_INET, &this_dev_stat->gdev_ip_network_order, dev_ip_str, sizeof(dev_ip_str));
+ MESA_handle_runtime_log(gdev_kp_log_handle, RLOG_LV_INFO, "[gdev_keepalive]", " %s timeout, delete it.\n", dev_ip_str);
+ }
+#endif
+ for(service_index = 0; service_index < MAX_VXLAN_SERVICE_NUM; service_index++){
+ if(this_dev_stat->service_array[service_index].keepalive_request_num > 0){
+ this_dev_stat->service_array[service_index].keepalive_request_num = 0;
+ this_dev_stat->service_array[service_index].keepalive_reply_num = 0;
+ }
+ }
+ }
+ }
+}
+
+
+static void *gdev_keepalive_log_thread(void *arg)
+{
+ time_t last_op_time = time(NULL);
+
+ MESA_mkdir_p(sapp_global_val->config.data_file_path.data_files_root_dir, 0755);
+
+ while(sapp_get_current_state() < SAPP_STATE_PROCESSING){
+ sapp_usleep(100);
+ }
+
+ while(sapp_get_current_state() == SAPP_STATE_PROCESSING){
+ while(last_op_time == time(NULL)){
+ sapp_usleep(100);
+ }
+ last_op_time = time(NULL);
+ __gdev_keepalive_pkt_calc_pps();
+ gdev_keepalive_update_local_log();
+ //gdev_keepalive_clear_stat(); /* ÿ����ռ���, ֻ����һ��ʱ������� */
+ }
+
+ return NULL;
+}
+
+static int gdev_kp_update_service_ctrl(const struct gdev_keepalive_service_ctrl *service_ctrl)
+{
+ if((service_ctrl->service_num < 0) || (service_ctrl->service_num >= MAX_VXLAN_SERVICE_NUM)){
+ return -1;
+ }
+
+ g_dev_keepalive_service_ctrl_array[service_ctrl->service_num].keepalive_switch = service_ctrl->keepalive_switch;
+
+ return 0;
+}
+
+
+
+/* vxlan���⻷����, vpn-id, Դ�˿ں�ҵ��ID֮��Ĺ�ϵ, �����ļ���ʽ:
+
+ service-id VPN-id Sport-range
+ 1 101 50000-50016
+ 2 102 50064-50080
+ ......
+
+ ���ڸ�֪�ϲ�Ӧ��ҵ���, �ʹ�������ҵ���Ƿ���Ҫ����.
+*/
+
+
+static int vxlan_sport_service_map_update(int service_id, unsigned short begin_sport_host, unsigned short end_sport_host)
+{
+ unsigned short i;
+
+ for(i = begin_sport_host; i <= end_sport_host;i++){
+ g_vxlan_sport_to_service_id[i] = service_id;
+ g_dev_keepalive_service_ctrl_array[service_id].keepalive_switch = 1;
+ }
+
+ return 0;
+}
+
+static int vxlan_sport_service_map_init(void)
+{
+ char line_buf[1024];
+ FILE *fp;
+ int tmp_service_id, tmp_int;
+ const char *delim = "\t- ";
+ char *save_ptr;
+ char *section;
+ unsigned short begin_sport, end_sport;
+
+ fp = fopen(ABBR_VXLAN_SPORT_MAP_CONF_FILE, "r");
+ if(NULL == fp){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "open vxlan sport map file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ return -1;
+ }
+
+ while(fgets(line_buf, 1024, fp) != NULL){
+ if('#' == line_buf[0]){
+ continue;
+ }
+ del_last_rn(line_buf, 1024);
+
+ /* service-id */
+ section = strtok_r(line_buf, delim, &save_ptr);
+ if(NULL == section){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+ tmp_service_id = atoi(section);
+
+ /* VPN-id, ��ʱ����ת��, ֱ�Ӽ�100����ҵ��� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ if(NULL == section){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+
+ /* begin-port */
+ section = strtok_r(NULL, delim, &save_ptr);
+ if(NULL == section){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+ tmp_int = atoi(section);
+ if(tmp_int <= 0 || tmp_int > 65535){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+ begin_sport = (unsigned short)tmp_int;
+
+ /* end-port */
+ section = strtok_r(NULL, delim, &save_ptr);
+ if(NULL == section){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+ tmp_int = atoi(section);
+ if(tmp_int <= 0 || tmp_int > 65535){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+ end_sport = (unsigned short)tmp_int;
+
+ if(end_sport < begin_sport){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "parse file %s error!\n", ABBR_VXLAN_SPORT_MAP_CONF_FILE);
+ goto done;
+ }
+
+ while(strtok_r(NULL, delim, &save_ptr));
+
+ vxlan_sport_service_map_update(tmp_service_id, begin_sport, end_sport);
+ }
+
+done:
+ fclose(fp);
+
+ return 0;
+}
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* �������vxlanģʽ��, ���ݰ��Ƿ�������� */
+int vxlan_packet_is_myself(const raw_pkt_t *rawpkt)
+{
+ struct mesa_ip4_hdr *ip4h = (struct mesa_ip4_hdr *)((char *)rawpkt->raw_pkt_data + sizeof(struct mesa_ethernet_hdr));
+
+ if(sendto_gdev_card_ip == ip4h->ip_dst.s_addr){
+ return 1;
+ }
+
+ return 0;
+}
+
+
+unsigned char vxlan_sport_map_to_service_id(unsigned short sport_host_order)
+{
+ return g_vxlan_sport_to_service_id[sport_host_order];
+}
+
+unsigned char vxlan_id_map_to_service_id(int vxlan_id)
+{
+ return (unsigned char)(vxlan_id - 100);
+}
+
+
+int gdev_keepalive_set_opt(const SAPP_TLV_T *tlv_value)
+{
+ int ret = 0;
+ static time_t last_log_time = 0;
+
+ if((NULL == tlv_value) || (tlv_value->length <= 0)){
+ return -1;
+ }
+
+ switch(tlv_value->type){
+ case GDEV_KEEPALIVE_OPT_SERVICE_CTRL:
+ {
+ if(tlv_value->length != sizeof(struct gdev_keepalive_service_ctrl)){
+ return -1;
+ }
+ const struct gdev_keepalive_service_ctrl *actual_val = (const struct gdev_keepalive_service_ctrl *)tlv_value->ptr_value;
+
+ ret = gdev_kp_update_service_ctrl(actual_val);
+ if(ret < 0){
+ if(last_log_time < g_CurrentTime){
+ last_log_time = g_CurrentTime;
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "set gdev-keepalive error! service:%d, action:%d",
+ actual_val->service_num, actual_val->keepalive_switch);
+ }
+ }else{
+ if(last_log_time < g_CurrentTime){
+ last_log_time = g_CurrentTime;
+ MESA_handle_runtime_log(gdev_kp_log_handle, 10, "[gdev_keepalive]", "set gdev-keepalive, service:%d, action:%d",
+ actual_val->service_num, actual_val->keepalive_switch);
+ }
+ }
+ }
+ break;
+
+ case GDEV_KEEPALIVE_OPT_GLOBAL_SWITCH:
+ {
+ if(tlv_value->length != sizeof(int)){
+ return -1;
+ }
+ g_dev_keepalive_flag = tlv_value->int_value;
+ if(last_log_time < g_CurrentTime){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 20, "[gdev_keepalive]", "set global keepalive to %d", tlv_value->int_value);
+ last_log_time = g_CurrentTime;
+ }
+ }
+ break;
+
+ default:
+ ret = -2;
+ break;
+ }
+
+ return ret;
+}
+
+int gdev_keepalive_get_opt(SAPP_TLV_T *tlv_value)
+{
+ int ret = 0;
+
+ if((NULL == tlv_value) || (tlv_value->length <= 0)){
+ return -1;
+ }
+
+ switch(tlv_value->type){
+
+ case GDEV_KEEPALIVE_OPT_GLOBAL_SWITCH:
+ {
+ tlv_value->int_value = g_dev_keepalive_flag;
+ }
+ break;
+
+ case GDEV_KEEPALIVE_OPT_RCV_PKT_PPS:
+ {
+ tlv_value->long_value = _gdev_keepalive_rcv_pps;
+ }
+ break;
+
+ case GDEV_KEEPALIVE_OPT_SND_PKT_PPS:
+ {
+ tlv_value->long_value = _gdev_keepalive_snd_pps;
+ }
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+
+char gdev_keepalive_udp_entry(const struct streaminfo *a_udp, void **pme, int thread_seq, const void *ip_hdr)
+{
+ int entry_ret = APP_STATE_GIVEME;
+ int kp_ret;
+ const struct streaminfo_private *a_udp_pr;
+
+ if(OP_STATE_PENDING == a_udp->opstate){
+ if(0 == gdev_bfd_pkt_identify(a_udp)){
+ return APP_STATE_DROPME;
+ }
+ }else if(OP_STATE_CLOSE == a_udp->opstate){
+ return APP_STATE_DROPME;
+ }
+
+ a_udp_pr = (const struct streaminfo_private *)a_udp;
+ kp_ret = gdev_keepalive_plug(a_udp_pr->raw_pkt, a_udp->threadnum, a_udp->routedir, GDEV_KEEPALIVE_TYPE_BFD);
+ if(kp_ret < 0){
+ /* ������, socket�ȴ����ܷ���APP_STATE_DROPME, ����DROP ME����Ҳ�ò������������, ���Dz������ͨ��gdev_keepalive_set_opt()�رձ����, ����Ҫ����DROPPKT, ���ܰ��������ע */
+ entry_ret = APP_STATE_GIVEME | APP_STATE_DROPPKT;
+ }else{
+ entry_ret = APP_STATE_GIVEME | APP_STATE_DROPPKT; /* �����, ������ǰ�� */
+ }
+
+ return entry_ret;
+}
+
+
+char gdev_keepalive_ip_entry(const struct streaminfo *pstream,unsigned char routedir,int thread_seq, const struct mesa_ip4_hdr *ipv4_hdr)
+{
+ const struct mesa_icmp_echo_hdr *icmp_hdr;
+ const struct streaminfo_private *pstream_pr;
+ int entry_ret = APP_STATE_GIVEME;
+ int kp_ret;
+
+ if(ipv4_hdr->ip_p != IPPROTO_ICMP){
+ return APP_STATE_DROPME;
+ }
+
+ if(ipv4_hdr->ip_dst.s_addr != sendto_gdev_card_ip){
+ return APP_STATE_DROPME;
+ }
+
+ icmp_hdr = (struct mesa_icmp_echo_hdr *)((char *)ipv4_hdr + ipv4_hdr->ip_hl*4);
+ if(icmp_hdr->icmp_type != ICMP_ECHO){
+ return APP_STATE_DROPME;
+ }
+
+ pstream_pr = (const struct streaminfo_private *)pstream;
+ kp_ret = gdev_keepalive_plug(pstream_pr->raw_pkt, thread_seq, pstream->routedir, GDEV_KEEPALIVE_TYPE_ICMP);
+ if(kp_ret < 0){
+ entry_ret = APP_STATE_DROPME | APP_STATE_DROPPKT;
+ }else{
+ entry_ret = APP_STATE_GIVEME | APP_STATE_DROPPKT; /* �����, ������ǰ�� */
+ }
+
+ return entry_ret;
+}
+
+
+int gdev_keepalive_plug_init(void)
+{
+ char tmp_ip_buf[16];
+ char deploy_mode_string[32];
+ int opt_len;
+ int i;
+
+ gdev_kp_log_handle = sapp_global_val->individual_fixed.log_handle;
+
+
+ /* ���߳�ģʽ��α��������, 64B������� */
+ assert(sizeof(gdev_keepalive_status_per_thread_t) % 64 == 0);
+
+ opt_len = sizeof(deploy_mode_string);
+ if(sapp_get_platform_opt(SPO_DEPLOYMENT_MODE_STR, (void *)deploy_mode_string, &opt_len) < 0){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 30, "[gdev_keepalive]",
+ "can't get sapp deployment mode!\n");
+ return -1;
+ }
+
+ if(strncasecmp(deploy_mode_string, "inline", strlen("inline")) != 0){ /* ��G����ģʽ */
+ MESA_handle_runtime_log(gdev_kp_log_handle, 30, "[gdev_keepalive]", "not inline mode, can't load gdev_keepalive.so\n");
+ return -1;
+ }
+
+ memset(g_vxlan_sport_to_service_id, 0, sizeof(g_vxlan_sport_to_service_id));
+
+ memset(tmp_ip_buf, 0, 16);
+ MESA_load_profile_string_nodef((char *)ABBR_INLINE_DEV_CONF_FILE, (char *)"Module", (char *)"sendto_gdev_ip", tmp_ip_buf, 16);
+ if(tmp_ip_buf[0] == '\0'){
+ MESA_handle_runtime_log(gdev_kp_log_handle, 30, "[gdev_keepalive]","can't get 'sendto_gdev_ip'");
+ return -1;
+ }
+
+ inet_pton(AF_INET, tmp_ip_buf, &sendto_gdev_card_ip);
+
+ MESA_load_profile_int_def((char *)ABBR_INLINE_DEV_CONF_FILE, (char *)"Module", (char *)"default_keepalive_action", &g_dev_keepalive_default_action, 1);
+
+
+ for(i = 0; i < MAX_VXLAN_SERVICE_NUM; i++){
+ g_dev_keepalive_service_ctrl_array[i].service_num = i;
+ g_dev_keepalive_service_ctrl_array[i].keepalive_switch = g_dev_keepalive_default_action;
+ }
+
+ vxlan_sport_service_map_init();
+
+ pthread_create(&sapp_global_val->individual_fixed.gdev_keepalive_log_thread_id, NULL, gdev_keepalive_log_thread, NULL);
+
+ return 0;
+}
+
+
+void gdev_keepalive_plug_destroy(void)
+{
+ if(DEPOLYMENT_MODE_INLINE != sapp_global_val->config.packet_io.depolyment_mode_bin){
+ return;
+ }
+
+ if(sapp_global_val->individual_fixed.gdev_keepalive_log_thread_id){
+ pthread_join(sapp_global_val->individual_fixed.gdev_keepalive_log_thread_id, NULL);
+ sapp_global_val->individual_fixed.gdev_keepalive_log_thread_id = 0;
+ }
+
+ memset(GDEV_KEEPALIVE_STAT, 0, sizeof(GDEV_KEEPALIVE_STAT));
+ memset((void *)g_dev_keepalive_service_ctrl_array, 0, sizeof(g_dev_keepalive_service_ctrl_array));
+ g_dev_keepalive_flag = 1;
+ g_dev_keepalive_default_action = 1;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+