netlink和NF_INET_LOCAL_OUT

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include  
#include
#include
#include
#include "elvs_kernel_vxlan.h"

#define MIN_VXLAN_HEAD_ROOM (sizeof(struct lb_vxlan_hdr) + sizeof(struct udphdr) + \
    sizeof(struct iphdr) + 18)

//cat /sys/module/elvs_kernel_vxlan/parameters/m_pkt_cnt
static long unsigned int m_pkt_cnt = 0;
module_param(m_pkt_cnt, ulong, 0644);
MODULE_PARM_DESC(m_pkt_cnt, "all packets sent");
static int m_ip_num = 0;
module_param(m_ip_num, int, 0644);
MODULE_PARM_DESC(m_ip_num, "exist ip numbers");
uint16_t m_free_list = INVALID_RSIP_POS;
uint16_t m_bucket_list[MAX_BUCKET_NUM];
struct elvs_ip_mgr m_ip_list[MAX_RSIP_NUM];

static int elvs_init_ip(void){
    int i=0;
    memset(m_bucket_list,0xff,sizeof(m_bucket_list));
    memset(m_ip_list,0,sizeof(m_ip_list));
    m_free_list = 0;
    for (i=0; i < (MAX_RSIP_NUM - 1); i++){
        m_ip_list[i].next = i+1;
    }
    m_ip_list[MAX_RSIP_NUM - 1].next = INVALID_RSIP_POS;
    return RET_SUCCESS;
}

static struct elvs_ip_mgr* elvs_get_ip(uint32_t overlay_ip){
    int bucket_pos = (overlay_ip >> 24)%MAX_BUCKET_NUM;
    int ip_pos = m_bucket_list[bucket_pos];
    while (ip_pos < MAX_RSIP_NUM){
        if (m_ip_list[ip_pos].overlay_ip == overlay_ip){
            return &m_ip_list[ip_pos];
        }
        ip_pos = m_ip_list[ip_pos].next;
    }
    return NULL;
}

static int elvs_add_ip(struct elvs_nl_cmd *ip_cmd){
    int bucket_pos = (ip_cmd->overlay_ip >> 24)%MAX_BUCKET_NUM;
    int ip_pos = m_free_list;
    if (NULL != elvs_get_ip(ip_cmd->overlay_ip)){
        return RET_EXIST;
    }
    if (ip_pos >= MAX_RSIP_NUM ){
        return RET_NORESOURCE;
    }
    m_free_list = m_ip_list[ip_pos].next;
    m_ip_list[ip_pos].overlay_ip  = ip_cmd->overlay_ip;
    m_ip_list[ip_pos].underlay_ip = ip_cmd->underlay_ip;
    m_ip_list[ip_pos].vni_id      = ip_cmd->vni_id;
    m_ip_list[ip_pos].next = m_bucket_list[bucket_pos];
    m_bucket_list[bucket_pos] = ip_pos;
    m_ip_num++;
    return RET_SUCCESS;
}

static int elvs_mod_ip(struct elvs_nl_cmd *ip_cmd){
    struct elvs_ip_mgr* ip_mgr = elvs_get_ip(ip_cmd->overlay_ip);
    if (NULL == ip_mgr){
        return RET_NOTEXIST;
    }
    ip_mgr->underlay_ip = ip_cmd->underlay_ip;
    ip_mgr->vni_id      = ip_cmd->vni_id;
    return RET_SUCCESS;
}

static int elvs_del_ip(struct elvs_nl_cmd *ip_cmd){
    uint32_t overlay_ip = ip_cmd->overlay_ip;
    int bucket_pos = (overlay_ip >> 24)%MAX_BUCKET_NUM;
    int ip_pos = m_bucket_list[bucket_pos];
    int last_pos = ip_pos;
    while (ip_pos < MAX_RSIP_NUM){
        if (m_ip_list[ip_pos].overlay_ip == overlay_ip){
            if (ip_pos == last_pos){//head
                m_bucket_list[bucket_pos] = m_ip_list[ip_pos].next;
            }else{
                m_ip_list[last_pos].next = m_ip_list[ip_pos].next;;
            }
            ip_cmd->underlay_ip = m_ip_list[ip_pos].underlay_ip;
            m_ip_list[ip_pos].next = m_free_list;
            m_free_list = ip_pos;
            if (m_ip_num > 0){
                m_ip_num--;
            }
            return RET_SUCCESS;
        }
        last_pos = ip_pos;
        ip_pos = m_ip_list[ip_pos].next;
    }
    return RET_NOTEXIST;
}

static struct sock *elvs_netlink_sock = NULL;

static void elvs_check_ip_empty_full(int cmd){
    int i = 0, free_list_num = 0;
    uint16_t free_list;
    if ((NETLINK_CMD_ADD != cmd) && (NETLINK_CMD_DEL != cmd)){
        return;
    }
    if (0 == m_ip_num){
        for (i = 0; i < MAX_BUCKET_NUM; i++){
            if (INVALID_RSIP_POS != m_bucket_list[i]){
                printk(KERN_INFO"%s: m_bucket_list[%d]=%u is not empty!\n",__func__, i,m_bucket_list[i]);
                return;
            }
        }
        free_list = m_free_list;
        while (INVALID_RSIP_POS != free_list){
            free_list_num++;
            free_list = m_ip_list[free_list].next;
        }
        if (free_list_num != MAX_RSIP_NUM){
            printk("KERN_INFO%s: free_list_num=%d %d\n",__func__, free_list_num,MAX_RSIP_NUM);
            return;
        }
        printk(KERN_INFO"%s: empty success!\n",__func__);
    }else if(MAX_RSIP_NUM == m_ip_num){
        if (INVALID_RSIP_POS != m_free_list){
            printk(KERN_INFO"%s: not empty m_free_list=%u %d\n",__func__, m_free_list, INVALID_RSIP_POS);
            return;
        }
        printk(KERN_INFO"%s: full success!\n",__func__);
    }
    return;
}

//audit_receive_msg
static int elvs_netlink_receive_msg(struct elvs_nl_cmd *cmd){
    int ret = RET_INVALID_CMD;
    char *cmd_str = "unknown";
    
    if (NETLINK_CMD_ADD == cmd->cmd){
        cmd_str = "add";
        ret = elvs_add_ip(cmd);
    }else if (NETLINK_CMD_MOD == cmd->cmd){
        cmd_str = "mod";
        ret = elvs_mod_ip(cmd);
    }else if (NETLINK_CMD_DEL == cmd->cmd){
        cmd_str = "del";
        ret = elvs_del_ip(cmd);
    }else if (NETLINK_CMD_GET == cmd->cmd){
        struct elvs_nl_cmd cmd_tmp;
        struct elvs_ip_mgr* mgr = elvs_get_ip(cmd->overlay_ip);
        if (NULL == mgr){
            ret = RET_NOTEXIST;
        }else{
            cmd_tmp.cmd = cmd->cmd;
            cmd_tmp.overlay_ip = mgr->overlay_ip;
            cmd_tmp.underlay_ip = mgr->underlay_ip;
            cmd = &cmd_tmp;
        }
        cmd_str = "get";
    }
    elvs_check_ip_empty_full(cmd->cmd);
    
    printk(KERN_DEBUG"elvs_netlink cmd[%s-%d] overlay_ip=0x%x underlay_ip=0x%x ret=%d ip_num=%d\n",
            cmd_str,cmd->cmd, ntohl(cmd->overlay_ip),ntohl(cmd->underlay_ip), ret,m_ip_num);
    
    return ret;
}

/* Receive messages from netlink socket. */
static void elvs_netlink_receive(struct sk_buff  *skb){
    struct nlmsghdr *nlh;
    struct elvs_nl_cmd *elvs_cmd;
    int len, err = RET_SUCCESS;
    
    if(!skb){
        return;
    }

    if(skb->len < NLMSG_SPACE(sizeof(struct elvs_nl_cmd))) {
        return;
    }
    
    nlh = nlmsg_hdr(skb);
    len = skb->len;
    //printk(KERN_DEBUG "elvs_netlink len=%u %u %u seq=%u pid=%u\n",
    //    nlh->nlmsg_len,NLMSG_ALIGN(nlh->nlmsg_len),len,
    //    nlh->nlmsg_seq,nlh->nlmsg_pid);
    while (nlmsg_ok(nlh, len)) {
        elvs_cmd = nlmsg_data(nlh);
        err = elvs_netlink_receive_msg(elvs_cmd);
        netlink_ack(skb, nlh, err);
        nlh = nlmsg_next(nlh, &len);
    }
}

static int elvs_netlink_init(void){
    struct netlink_kernel_cfg cfg;
    memset(&cfg,0,sizeof(cfg));
    cfg.input = elvs_netlink_receive;
    elvs_netlink_sock = netlink_kernel_create(&init_net, ELVS_NETLINK_ID, &cfg);
    if (!elvs_netlink_sock){
        printk("netlink_kernel_create fail!\n");
        return -1;
    }
    printk("netlink_kernel_create success!\n");
    return 0;
}

static int elvs_netlink_exit(void){
    if (elvs_netlink_sock){
        netlink_kernel_release(elvs_netlink_sock);
    }
    return 0;
}
static int elvs_ip_route_outer(struct sk_buff *skb, struct iphdr *ip,struct iphdr *ip_outer){
    struct dst_entry *dst_old = skb_dst(skb);
    struct rtable *rt;
    struct net *net_out;
    if (NULL == dst_old){
        printk(KERN_INFO "dst_old is NULL!\n");
        return -1;
    }
    if (NULL == dst_old->dev){
        printk(KERN_INFO "dst_old->dev is NULL!\n");
        return -1;
    }
    net_out = dev_net(dst_old->dev);
    if (NULL == net_out){
        printk(KERN_INFO "net_out is NULL!\n");
        return -1;
    }

    rt = ip_route_output(net_out, ip_outer->daddr, ip->saddr,0,0);
    if (IS_ERR(rt)){
        printk(KERN_INFO "ip_route_output fail! rt=%p\n",rt);
        return -1;
    }

    /* Drop old route. */
    skb_dst_drop(skb);
    skb_dst_set(skb, &rt->dst);

    if (skb_dst(skb)->error){
        printk(KERN_INFO "skb_dst(skb)->error=%d!\n",skb_dst(skb)->error);
        return -1;
    }

    return 0;
}


static unsigned int nf_elvs_vxlan_fn(void *priv,
                  struct sk_buff *skb,
                  const struct nf_hook_state *state){
    //return nf_nat_ipv6_local_fn(ops, skb, state, ip6table_nat_do_chain);
    struct iphdr *ip, *outer_ip;
    struct udphdr  *udp;
    struct lb_vxlan_hdr *vxlan;
    struct elvs_ip_mgr* ip_mgr;
    bool sysctl_vxlan_hdr_csum = false;
    uint8_t tos = 0;
    ip = ip_hdr(skb);
    if ((skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr))){
        return NF_ACCEPT;
    }
    //skb->dev is null!
    //state->out->namet=Ethernet1
    //printk(KERN_INFO "state->out->namet=%s\n",state->out->name);
    //daddr=0x11010102 saddr=0x11010101 head_room=244
    //printk(KERN_INFO "daddr=0x%x saddr=0x%x head_room=%d\n",ntohl(ip->daddr),ntohl(ip->saddr),head_room);
    //protocol=6 m_pkt_cnt=196 skb->csum=1048840
    //printk(KERN_INFO "protocol=%u m_pkt_cnt=%lu skb->csum=%u\n",ip->protocol,m_pkt_cnt,skb->csum);
    ip_mgr = elvs_get_ip(ip->daddr);
    if (NULL == ip_mgr){
        return NF_ACCEPT;
    }
    
    skb_cow_head(skb,MIN_VXLAN_HEAD_ROOM);
    if (skb_headroom(skb) < MIN_VXLAN_HEAD_ROOM){
        return NF_ACCEPT;//use old dst
    }
    printk(KERN_INFO "\nprotocol=%u daddr=0x%x saddr=0x%x head_room=%d %lu oif=%s\n",ip->protocol, ntohl(ip->daddr),ntohl(ip->saddr),
        skb_headroom(skb),MIN_VXLAN_HEAD_ROOM,state->out->name);

    
    vxlan = (struct lb_vxlan_hdr *)skb_push(skb, sizeof(struct udphdr));
    vxlan->version = 1;
    vxlan->tunnel_id = ip_mgr->vni_id;
   
    udp = (struct udphdr *)skb_push(skb, sizeof(struct udphdr));
    skb_reset_transport_header(skb);
    udp->check = 0;
    udp->dest = ntohs(10240);
    udp->source = ntohs(10240);
    udp->len = ntohs(skb->len);
    
    outer_ip = (struct iphdr *)skb_push(skb, sizeof(struct iphdr));
    skb_reset_network_header(skb);
    *((uint16_t *) outer_ip) = htons((4 << 12) | (5 << 8) | (tos & 0xff));
    outer_ip->tot_len = htons(skb->len);
    outer_ip->frag_off = htons(IP_DF);
    outer_ip->ttl = IPDEFTTL;
    outer_ip->protocol = IPPROTO_UDP;
    outer_ip->saddr = ip->saddr;
    outer_ip->daddr = ip_mgr->underlay_ip;
    
    ip_send_check(outer_ip);
    udp->check = 0;
    if (sysctl_vxlan_hdr_csum) {
        skb->csum = skb_checksum(skb, sizeof(struct iphdr), skb->len - sizeof(struct iphdr), 0);
        udp->check = csum_tcpudp_magic(outer_ip->saddr, outer_ip->daddr,skb->len - sizeof(struct iphdr), 
                                                IPPROTO_UDP, skb->csum);
    }
    //elvs_ip_route_outer(skb,ip,outer_ip);
    //printk(KERN_INFO "ip daddr=0x%x saddr=0x%x head_room=%d\n",ntohl(ip->daddr),ntohl(ip->saddr),head_room);
    printk(KERN_INFO "outer_ip daddr=0x%x saddr=0x%x\n",ntohl(outer_ip->daddr),ntohl(outer_ip->saddr));
    printk(KERN_INFO "protocol=%u m_pkt_cnt=%lu skb->csum=%u\n",ip->protocol,m_pkt_cnt,skb->csum);
    
    m_pkt_cnt++;
    //return dst_output_sk(skb->sk, skb);
    return NF_ACCEPT;
}

static struct nf_hook_ops nf_elvs_vxlan_ops[] __read_mostly = {
    {
        .hook        = nf_elvs_vxlan_fn,
        .pf            = NFPROTO_IPV4,
        .hooknum    = NF_INET_LOCAL_OUT,
        .priority    = 101,
        // 101 (after NF_IP_PRI_NAT_SRC)will route first, state->out->namet=
    },
};

static int __init elvs_vxlan_register(void){
    int err;
    elvs_init_ip();
    err = nf_register_hooks(nf_elvs_vxlan_ops, ARRAY_SIZE(nf_elvs_vxlan_ops));
    if (err < 0){
        printk("nf_register_hooks fail! err=%d\n",err);
        return err;
    }
    err = elvs_netlink_init();
    if (err < 0){
        printk("elvs_netlink_init fail! err=%d\n",err);
        return err;
    }
    printk("elvs_vxlan_register success!\n");
    return 0;
}

static void __exit elvs_vxlan_unregister(void){
    elvs_netlink_exit();
    nf_unregister_hooks(nf_elvs_vxlan_ops, ARRAY_SIZE(nf_elvs_vxlan_ops));
    printk("elvs_vxlan_unregister success\n");
}

module_init(elvs_vxlan_register);
module_exit(elvs_vxlan_unregister);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ELVS KERNEL VXLAN OPERATIONS");

 

 

================================

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include
#include
#include
#include
#include "elvs_kernel_vxlan.h"
//#include "elvs_kernel_tmp.c" for test

struct elvs_nl_sk{
  int sock;
  struct sockaddr_nl src_snl;
  struct sockaddr_nl dst_snl;
};
struct elvs_nl_msg{
  struct nlmsghdr nlhdr;
  struct elvs_nl_cmd cmd;
};

struct elvs_nl_sk m_elvs_nl_sk;
struct elvs_nl_msg m_elvs_nl_msg;
struct iovec m_elvs_nl_iov;
struct msghdr m_elvs_nl_sndmsg; 

static uint32_t m_nlmsg_seq = 0;
int netlink_send(struct elvs_nl_cmd *cmd){
    int status;
    memcpy(&m_elvs_nl_msg.cmd,cmd,sizeof(struct elvs_nl_cmd));
    m_elvs_nl_msg.nlhdr.nlmsg_seq++;
    status = sendmsg (m_elvs_nl_sk.sock, &m_elvs_nl_sndmsg, MSG_DONTWAIT);
    if (status < 0){
        printf("%s: sendmsg fail! status=%d %s\n",__func__,status, strerror(errno));
        return -1;
    }
    printf("%s: sendmsg success! status=%d %s\n",__func__,status, strerror(errno));
    return 0;

}

void netlink_receive(struct elvs_nl_sk *nl_sk){
    char buf[1024];
    struct iovec iov = {.iov_base = buf, .iov_len = sizeof buf};
    struct sockaddr_nl snl;
    struct msghdr msg = {.msg_name = (void *)&snl,
                 .msg_namelen = sizeof snl,
                 .msg_iov = &iov,
                 .msg_iovlen = 1};
    struct nlmsghdr *h;
    int status = recvmsg(nl_sk->sock, &msg, 0);
    if (status < 0) {
        printf("netlink_receive recvmsg! error status=%d errno=%d-%s\n",status,errno,strerror(errno));
        return;
    }
    h = (struct nlmsghdr *)buf;
    for (; NLMSG_OK(h, (unsigned int)status);h = NLMSG_NEXT(h, status)) {
        if (h->nlmsg_type == NLMSG_DONE)/* Finish of reading. */{
            printf("netlink_receive NLMSG_DONE=%d!\n",NLMSG_DONE);
            return;
        }

        if (h->nlmsg_type == NLMSG_ERROR) {
            struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h);
            int errnum = err->error;
            printf("netlink_receive response ret=%d!\n",err->error);
            if (RET_SUCCESS == err->error) {
                if (!(h->nlmsg_flags & NLM_F_MULTI))
                    return;
                continue;
            }
        }
    }
}

static int elvs_nl_init(void){
    int ret;
    struct timeval tv = {2,0};
    memset(&m_elvs_nl_sk,0,sizeof(m_elvs_nl_sk));
    m_elvs_nl_sk.src_snl.nl_family = AF_NETLINK;
    m_elvs_nl_sk.src_snl.nl_pid = getpid();
    m_elvs_nl_sk.src_snl.nl_groups = 0;

    m_elvs_nl_sk.dst_snl.nl_family = AF_NETLINK;
    m_elvs_nl_sk.dst_snl.nl_pid = 0; //to kernel
    m_elvs_nl_sk.dst_snl.nl_groups = 0;

    
    m_elvs_nl_sk.sock = socket(AF_NETLINK, SOCK_RAW, ELVS_NETLINK_ID);
    if (m_elvs_nl_sk.sock < 0) {
        printf("%s: open socket fail!: %s", __func__, strerror(errno));
        return -1;
    }

    ret = bind(m_elvs_nl_sk.sock, (struct sockaddr *)(&m_elvs_nl_sk.src_snl), sizeof(struct sockaddr_nl));
    if (ret < 0) {
        printf("%s:bind fail ret=%d %s", __func__,ret, strerror(errno));
        close(m_elvs_nl_sk.sock);
        return -1;
    }
    ret = setsockopt(m_elvs_nl_sk.sock, SOL_SOCKET,SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
    if (ret < 0) {
        printf("%s:setsockopt fail ret=%d %s", __func__,ret, strerror(errno));
        close(m_elvs_nl_sk.sock);
        return -1;
    }

    memset(&m_elvs_nl_msg,0,sizeof(m_elvs_nl_msg));
    m_elvs_nl_msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct elvs_nl_cmd));
    m_elvs_nl_msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    m_elvs_nl_msg.nlhdr.nlmsg_pid = getpid();

    memset(&m_elvs_nl_iov,0,sizeof(m_elvs_nl_iov));
    m_elvs_nl_iov.iov_base = (void *)(&m_elvs_nl_msg);
    m_elvs_nl_iov.iov_len = m_elvs_nl_msg.nlhdr.nlmsg_len;

    memset(&m_elvs_nl_sndmsg,0,sizeof(m_elvs_nl_sndmsg));
    m_elvs_nl_sndmsg.msg_name = (void *)&(m_elvs_nl_sk.dst_snl);
    m_elvs_nl_sndmsg.msg_namelen = sizeof(m_elvs_nl_sk.dst_snl);
    m_elvs_nl_sndmsg.msg_iov = &m_elvs_nl_iov;
    m_elvs_nl_sndmsg.msg_iovlen = 1;
    return RET_SUCCESS;    
}

int elvs_nl_oper(int cmd, uint32_t overlay_ip, uint32_t underlay_ip){
    int ret;
    struct elvs_nl_cmd elvs_cmd;
    elvs_cmd.cmd = cmd;
    elvs_cmd.overlay_ip = overlay_ip;
    elvs_cmd.underlay_ip = underlay_ip;
    //elvs_netlink_receive_msg(&elvs_cmd); for test
    netlink_send(&elvs_cmd);
    netlink_receive(&m_elvs_nl_sk);
    printf("\n");
    return 0;
}

int dpvs_laddr_main(int argc, char **argv){
    char *pro_name = argv[0];
    int opt = 0;
    char *const optstring = "-";
    uint32_t ip_out;
    uint16_t port_out = 0;
    uint16_t proto = IPPROTO_TCP;
    
    static struct option long_options[] = {
        {"print", no_argument, NULL, CMD_DPVS_LADDR_PRINT},
        {"svc-print", required_argument, NULL, CMD_DPVS_LADDR_SVC_PRINT},
        {"free-print", no_argument, NULL, CMD_DPVS_LADDR_FREE_PRINT},
        {"load", no_argument, NULL, CMD_DPVS_LADDR_LOAD},
        {"force-clear", no_argument, NULL, CMD_DPVS_LADDR_FORCE_CLEAR},
        {"tcp", no_argument, NULL, CMD_DPVS_LADDR_SVC_TCP},
        {"udp", no_argument, NULL, CMD_DPVS_LADDR_SVC_UDP},
        {"help", no_argument, NULL, CMD_DPVS_LADDR_HELP},
        {0, 0, 0, 0},
    };
    optind = 1;
    while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1){
        switch(opt) {
            case CMD_DPVS_LADDR_HELP:
                dpvs_laddr_usage(argv[0]);
                return 0;
            case CMD_DPVS_LADDR_PRINT:
                dpvs_laddr_dpvs_cmd(SOCKOPT_LADDR_MGR_GET);
                return 0;
            case CMD_DPVS_LADDR_LOAD:
                dpvs_laddr_dpvs_cmd(SOCKOPT_LADDR_MGR_LOAD);
                return 0;
            case CMD_DPVS_LADDR_FORCE_CLEAR:
                dpvs_laddr_dpvs_cmd(SOCKOPT_LADDR_MGR_FORCE_CLEAR);
                return 0;
            case CMD_DPVS_LADDR_FREE_PRINT:
                dpvs_laddr_svc_get(0,0,0);
                return 0;

            case CMD_DPVS_LADDR_SVC_PRINT:
                if (!dpvs_admin_utils_iport_get(optarg,&ip_out,&port_out)){
                    fprintf(stderr, "invalid %s\n",optarg);
                    return 0;
                }
                if ((0 == port_out) || (0 == ip_out)){
                    fprintf(stderr, "invalid %s\n",optarg);
                    return 0;
                }
                break;

            case CMD_DPVS_LADDR_SVC_TCP:
                proto = IPPROTO_TCP;
                break;

            case CMD_DPVS_LADDR_SVC_UDP:
                proto = IPPROTO_UDP;
                break;

            default:
                fprintf(stderr, "[ERR]: not support option=%d!\n",opt);
                dpvs_laddr_usage(pro_name);
                return -1;
        }
    }
    if ((0 == port_out) || (0 == ip_out)){
        fprintf(stderr, "please input ip:port\n");
        dpvs_laddr_usage(pro_name);
        return 0;
    }
    dpvs_laddr_svc_get(ip_out,port_out,proto);
    return 0;
}


int main(int argc, char **argv){
    int ret;
    uint32_t overlay_ip = ntohl(0x11010102);
    uint32_t underlay_ip = ntohl(0x11010202);
    //tmp_main(); for test
    ret = elvs_nl_init();
    if (ret < 0){
        return -1;
    }
    elvs_nl_oper(NETLINK_CMD_ADD, overlay_ip, underlay_ip);
    #if 0
    ret = ret;
    for (overlay_ip=0; overlay_ip <= MAX_RSIP_NUM; overlay_ip++){
        elvs_nl_oper(NETLINK_CMD_ADD, ntohl(overlay_ip), ntohl(overlay_ip + 0xf00000));
    }
    
    for (overlay_ip=1; overlay_ip <= MAX_RSIP_NUM; overlay_ip+=3){
        elvs_nl_oper(NETLINK_CMD_DEL, ntohl(overlay_ip),0);
        elvs_nl_oper(NETLINK_CMD_DEL, ntohl(overlay_ip-1),0);
        elvs_nl_oper(NETLINK_CMD_DEL, ntohl(overlay_ip+1),0);
    }
    for (overlay_ip=0; overlay_ip <= MAX_RSIP_NUM; overlay_ip++){
        elvs_nl_oper(NETLINK_CMD_GET, ntohl(overlay_ip), 0);
    }
    #endif
    return 0;
}

你可能感兴趣的:(linux系统及命令)