Browse files

vxlan becomes forwarding daemon. and config using vxlanctl

  • Loading branch information...
1 parent 292fe62 commit 9040ce2a26a23de91dcce43dda0f3b810504aacf upa committed Apr 27, 2012
Showing with 853 additions and 241 deletions.
  1. +2 −0 .gitignore
  2. +7 −4 common.h
  3. +499 −0 control.c
  4. +49 −0 control.h
  5. +1 −0 fdb.c
  6. +50 −0 hash.c
  7. +2 −0 hash.h
  8. +1 −0 iftap.c
  9. +85 −72 main.c
  10. +9 −6 makefile
  11. +0 −5 net.h
  12. +35 −146 vxlan.c
  13. +8 −8 vxlan.h
  14. +105 −0 vxlanctl.c
View
2 .gitignore
@@ -7,3 +7,5 @@ autom4te.cache/
m.sh
*.log
missing
+vxland
+vxlanctl
View
11 common.h
@@ -16,10 +16,11 @@
#define VXLAN_TUNNAME "vxlan"
#define VXLAN_PACKET_BUF_LEN 9216
-
#define VXLAN_LOGNAME "vxlan"
#define VXLAN_LOGFACILITY LOG_LOCAL7
+#define VXLAN_UNIX_DOMAIN "/var/run/vxlan"
+
#define ACL_MASK_RA 0x01
#define ACL_MASK_RS 0x02
@@ -41,13 +42,15 @@ struct vxlan_instance {
struct vxlan {
int udp_sock;
int unicast_sock;
+ int control_sock;
unsigned short port;
struct sockaddr_storage mcast_addr; /* vxlan Multicast Address */
- int vins_num; /* Num of VXLAN Instance */
- struct hash vins_tuple; /* VXLAN Instance hash table. key is VNI */
- struct vxlan_instance ** vins; /* VXLAN Instance List */
+ int vins_num; /* Num of VXLAN Instance */
+ struct hash vins_tuple; /* VXLAN Instance hash table. key is VNI */
+
+ pthread_t control_tid; /* Control Thread ID */
};
View
499 control.c
@@ -0,0 +1,499 @@
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <linux/un.h>
+
+
+#include "error.h"
+#include "common.h"
+#include "control.h"
+#include "net.h"
+#include "vxlan.h"
+
+
+void exec_command_invalid (char * str, int sock);
+void exec_command_vni_create (char * str, int sock);
+void exec_command_vni_destroy (char * str, int sock);
+void exec_command_acl (char * str, int sock);
+
+void (* exec_command_func[]) (char * str, int sock) =
+{
+ exec_command_invalid,
+ exec_command_vni_create,
+ exec_command_vni_destroy,
+ exec_command_acl
+};
+
+
+
+/* strtoaclentry related */
+#define ACLCMD_VNI 0
+#define ACLCMD_TYPE 1
+#define ACLCMD_ACT 2
+#define ACLCMD_OPT 3
+
+int
+strtoaclentry (char * str, struct acl_entry * e)
+{
+ int argc;
+ char * c;
+ char * args[CONTROL_ARG_MAX];
+ int mac[ETH_ALEN];
+ struct acl_entry entry;
+
+ memset (&entry, 0, sizeof (entry));
+ memset (args, 0, sizeof (args));
+
+ /* parse */
+ for (argc = 0, c = str; *c == ' '; c++);
+ while (*c && argc < CONTROL_ARG_MAX) {
+ args[argc++] = c;
+ while (*c && *c > ' ') c++;
+ while (*c && *c <= ' ') *c++ = '\0';
+ }
+
+ strtovni (args[ACLCMD_VNI], entry.vni);
+
+
+ if (strncmp (args[ACLCMD_TYPE], "mac", 3) == 0) {
+ /* MAC Address Filter */
+ if (argc < 4)
+ return -1;
+
+ if (sscanf (args[ACLCMD_OPT], "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1],
+ &mac[2], &mac[3], &mac[4], &mac[5]) < 6)
+ return -1;
+
+ entry.type = ACL_TYPE_MAC;
+ entry.term_mac[0] = mac[0];
+ entry.term_mac[1] = mac[1];
+ entry.term_mac[2] = mac[2];
+ entry.term_mac[3] = mac[3];
+ entry.term_mac[4] = mac[4];
+ entry.term_mac[5] = mac[5];
+
+ memcpy (e, &entry, sizeof (entry));
+
+
+ } else if (strncmp (args[ACLCMD_TYPE], "ns", 2) == 0) {
+ /* IPv6 Neighbor Solicit Filter */
+ if (argc < 4)
+ return -1;
+
+ entry.type = ACL_TYPE_IP6;
+ if (inet_pton (AF_INET6, args[ACLCMD_OPT], &entry.term_ip6) < 1)
+ return -1;
+
+ memcpy (e, &entry, sizeof (entry));
+
+
+ } else if (strncmp (args[ACLCMD_TYPE], "arp", 3) == 0) {
+ /* ARP Filter */
+
+ if (argc < 4)
+ return -1;
+
+ entry.type = ACL_TYPE_IP4;
+ if (inet_pton (AF_INET, args[ACLCMD_OPT], &entry.term_ip4) < 1)
+ return -1;
+
+ memcpy (e, &entry, sizeof (entry));
+
+ } else if (strncmp (args[ACLCMD_TYPE], "ra", 2)) {
+ /* ARP Filter */
+
+ entry.type = ACL_TYPE_RA;
+ memcpy (e, &entry, sizeof (entry));
+
+
+ } else if (strncmp (args[ACLCMD_TYPE], "rs", 2)) {
+ /* Router Solicit Filter */
+
+ entry.type = ACL_TYPE_RS;
+ memcpy (e, &entry, sizeof (entry));
+ }
+
+#define STRTOACLENTRY_INSTALL 1
+#define STRTOACLENTRY_UNINSTALL 2
+ if (strncmp (args[ACLCMD_ACT], "deny", 4) == 0)
+ return STRTOACLENTRY_INSTALL;
+
+ if (strncmp (args[ACLCMD_ACT], "permit", 6) == 0)
+ return STRTOACLENTRY_UNINSTALL;
+
+
+ return -1;
+}
+
+
+
+int
+install_acl_entry (struct vxlan_instance * vins, struct acl_entry ae)
+{
+ struct acl_entry * e;
+
+ if (vins == NULL)
+ return -1;
+
+ if (CHECK_VNI (vins->vni, ae.vni) < 0)
+ return -1;
+
+ e = (struct acl_entry *) malloc (sizeof (struct acl_entry));
+ memset (e, 0, sizeof (struct acl_entry));
+ memcpy (e, &ae, sizeof (ae));
+
+ switch (e->type) {
+ case ACL_TYPE_MAC :
+ insert_hash (&vins->acl_mac, e, &e->term_mac);
+ break;
+ case ACL_TYPE_IP4 :
+ insert_hash (&vins->acl_ip4, e, &e->term_ip4);
+ break;
+ case ACL_TYPE_IP6 :
+ insert_hash (&vins->acl_ip6, e, &e->term_ip6);
+ break;
+ case ACL_TYPE_RA :
+ vins->acl_mask |= ACL_MASK_RA;
+ break;
+ case ACL_TYPE_RS :
+ vins->acl_mask |= ACL_MASK_RS;
+ break;
+
+ default :
+ return -1;
+ }
+
+ return 1;
+}
+
+int
+uninstall_acl_entry (struct vxlan_instance * vins, struct acl_entry ae)
+{
+ struct acl_entry * e;
+
+ if (vins == NULL)
+ return -1;
+
+ if (CHECK_VNI (vins->vni, ae.vni) < 0)
+ return -1;
+
+ e = (struct acl_entry *) malloc (sizeof (struct acl_entry));
+ memset (e, 0, sizeof (struct acl_entry));
+ memcpy (e, &ae, sizeof (ae));
+
+ switch (e->type) {
+ case ACL_TYPE_MAC :
+ delete_hash (&vins->acl_mac, &e->term_mac);
+ break;
+ case ACL_TYPE_IP4 :
+ delete_hash (&vins->acl_ip4, &e->term_ip4);
+ break;
+ case ACL_TYPE_IP6 :
+ delete_hash (&vins->acl_ip6, &e->term_ip6);
+ break;
+ case ACL_TYPE_RA :
+ vins->acl_mask ^= ACL_MASK_RA;
+ break;
+ case ACL_TYPE_RS :
+ vins->acl_mask ^= ACL_MASK_RS;
+ break;
+ default :
+ return -1;
+ }
+
+ return 1;
+}
+
+
+
+
+void * process_vxlan_control (void * param);
+int create_unix_server_socket (char * domain);
+int strtocmdtype (char * str);
+
+void
+init_vxlan_control (void)
+{
+ pthread_attr_t attr;
+
+ pthread_attr_init (&attr);
+// pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create (&vxlan.control_tid, &attr, process_vxlan_control, NULL);
+
+ return;
+}
+
+void *
+process_vxlan_control (void * param)
+{
+ char * c;
+ int socket, accept_socket;
+ char buf[CONTROL_MSG_BUF_LEN];
+ fd_set fds;
+
+ socket = create_unix_server_socket (VXLAN_UNIX_DOMAIN);
+ vxlan.control_sock = socket;
+
+ listen (socket, 1);
+
+ while (1) {
+ memset (buf, 0, sizeof (buf));
+
+ FD_ZERO (&fds);
+ FD_SET (socket, &fds);
+ pselect (socket + 1, &fds, NULL, NULL, NULL, NULL);
+
+ if (!FD_ISSET (socket, &fds))
+ break;
+
+ accept_socket = accept (socket, NULL, 0);
+
+ if (read (accept_socket, buf, sizeof (buf)) < 0) {
+ warn ("read(2) faild : control socket");
+ shutdown (accept_socket, 1);
+ close (accept_socket);
+ continue;
+ }
+
+ for (c = buf; *c == ' '; c++);
+
+ exec_command_func[strtocmdtype (c)] (c, accept_socket);
+
+ if (shutdown (accept_socket, SHUT_RDWR) != 0) {
+ error_warn ("%s : shutdown : %s", __func__, strerror (errno));
+ }
+
+ if (close (accept_socket) != 0) {
+ error_warn ("%s : close : %s", __func__, strerror (errno));
+ }
+ }
+
+ shutdown (vxlan.control_sock, SHUT_RDWR);
+ if (close (vxlan.control_sock) < 0)
+ error_warn ("%s : close control socket failed : %s", strerror (errno));
+
+ /* not reached */
+ return NULL;
+}
+
+
+int
+strtocmdtype (char * str)
+{
+ if (strncmp (str, "create", 6) == 0)
+ return COMMAND_TYPE_VNI_CREATE;
+
+ if (strncmp (str, "destroy", 7) == 0)
+ return COMMAND_TYPE_VNI_DESTROY;
+
+ if (strncmp (str, "acl", 3) == 0)
+ return COMMAND_TYPE_ACL;
+
+ return COMMAND_TYPE_INVALID;
+}
+
+
+void
+strtocontrol (char * str)
+{
+ char type[16];
+ char args[512];
+
+ if (sscanf (str, "%s %s", type, args) < 2) {
+ error_warn ("invalid control message \"%s\"", str);
+ return;
+ }
+
+ return;
+}
+
+
+
+void
+exec_command_invalid (char * str, int sock)
+{
+ write (sock, CONTROL_ERRMSG, sizeof (CONTROL_ERRMSG));
+ return;
+}
+
+void
+exec_command_vni_create (char * str, int sock)
+{
+ u_int8_t vnibuf[3];
+ char cmd[CONTROL_CMD_BUF_LEN];
+ char vni[CONTROL_CMD_BUF_LEN];
+ struct vxlan_instance * vins;
+
+ if (sscanf (str, "%s %s", cmd, vni) < 2) {
+ write (sock, CONTROL_ERRMSG, sizeof (CONTROL_ERRMSG));
+ return;
+ }
+
+ strtovni (vni, vnibuf);
+
+ if ((vins = search_hash (&vxlan.vins_tuple, vnibuf)) != NULL) {
+ char errbuf[] = "this vxlan instance exists\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ vins = create_vxlan_instance (vnibuf);
+ insert_hash (&vxlan.vins_tuple, vins, vnibuf);
+ init_vxlan_instance (vins);
+ vxlan.vins_num++;
+
+ char msgbuf[] = "created\n";
+ write (sock, msgbuf, strlen (msgbuf));
+ return;
+}
+
+
+void
+exec_command_vni_destroy (char * str, int sock)
+{
+ u_int8_t vnibuf[3];
+ char cmd[CONTROL_CMD_BUF_LEN];
+ char vni[CONTROL_CMD_BUF_LEN];
+ struct vxlan_instance * vins;
+
+ if (sscanf (str, "%s %s", cmd, vni) < 2) {
+ write (sock, CONTROL_ERRMSG, sizeof (CONTROL_ERRMSG));
+ return;
+ }
+
+ strtovni (vni, vnibuf);
+ if ((vins = search_hash (&vxlan.vins_tuple, vnibuf)) == NULL) {
+ char errbuf[] = "this vxlan instance does not exists\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ if (destroy_vxlan_instance (vins) < 0) {
+ char errbuf[] = "Delete vxlan instance failed\n";
+ write (sock, errbuf, strlen (errbuf));
+
+ } else {
+ char errbuf[] = "Deleted\n";
+ write (sock, errbuf, strlen (errbuf));
+ }
+
+ return;
+}
+
+
+void
+exec_command_acl (char * str, int sock)
+{
+
+ int n;
+ struct acl_entry ae;
+
+ struct vxlan_instance * vins;
+
+ if ((n = strtoaclentry (str + 4, &ae)) < 0) {
+ char errbuf[] = "inavlid acl entry\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ if ((vins = search_hash (&vxlan.vins_tuple, ae.vni)) == NULL) {
+ char errbuf[] = "this vni instance does not exist\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ if (n == STRTOACLENTRY_INSTALL) {
+ if (install_acl_entry (vins, ae) < 0) {
+ char errbuf[] = "install access list failed\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ } else {
+ char errbuf[] = "access list installed\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+ }
+
+ if (n == STRTOACLENTRY_UNINSTALL) {
+ if (uninstall_acl_entry (vins, ae) < 0) {
+ char errbuf[] = "uninstall access list failed\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ } else {
+ char errbuf[] = "access list uninstalled\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+ }
+
+ return;
+}
+
+/*
+
+void
+exec_command_acl_del (char * str, int sock)
+{
+
+ struct acl_entry ae;
+ struct vxlan_instance * vins;
+
+ if (strtoaclentry (str + 7, &ae) < 0) {
+ char errbuf[] = "inavlid acl entry\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ if ((vins = search_hash (&vxlan.vins_tuple, ae.vni)) == NULL) {
+ char errbuf[] = "this vni instance does not exist\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ if (uninstall_acl_entry (vins, ae) < 0) {
+ char errbuf[] = "uninstall access list failed\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+ }
+
+ char errbuf[] = "access list uninstalled\n";
+ write (sock, errbuf, strlen (errbuf));
+ return;
+
+}
+
+*/
+
+
+
+
+int
+create_unix_server_socket (char * domain)
+{
+ int sock;
+ struct sockaddr_un saddru;
+
+ memset (&saddru, 0, sizeof (saddru));
+ saddru.sun_family = AF_UNIX;
+ strncpy (saddru.sun_path, domain, UNIX_PATH_MAX);
+
+ if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ err (EXIT_FAILURE, "can not create unix socket");
+
+ if (bind (sock, (struct sockaddr *)&saddru, sizeof (saddru)) < 0) {
+ printf ("%s exists\n", VXLAN_UNIX_DOMAIN);
+ exit (-1);
+ }
+
+ return sock;
+}
+
View
49 control.h
@@ -0,0 +1,49 @@
+#ifndef _CONTROLL_H_
+#define _CONTROLL_H_
+
+/* access list related type */
+
+#define ACL_TYPE_MAC 0
+#define ACL_TYPE_IP4 1
+#define ACL_TYPE_IP6 2
+#define ACL_TYPE_RA 3
+#define ACL_TYPE_RS 4
+
+
+struct acl_entry {
+ int type;
+ u_int8_t vni[VXLAN_VNISIZE];
+
+ union {
+ u_int8_t mac[ETH_ALEN];
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ } term;
+};
+#define term_mac term.mac
+#define term_ip4 term.addr4
+#define term_ip6 term.addr6
+
+int strtoaclentry (char * str, struct acl_entry * e);
+int install_acl_entry (struct vxlan_instance * vins, struct acl_entry ae);
+int uninstall_acl_entry (struct vxlan_instance * vins, struct acl_entry ae);
+
+
+#define CONTROL_MSG_BUF_LEN 2048
+#define CONTROL_CMD_BUF_LEN 256
+#define CONTROL_ARG_MAX 16
+
+void init_vxlan_control (void);
+
+
+#define COMMAND_TYPE_INVALID 0
+#define COMMAND_TYPE_VNI_CREATE 1
+#define COMMAND_TYPE_VNI_DESTROY 2
+#define COMMAND_TYPE_ACL 3
+#define COMMAND_TYPE_SHOW 5
+
+
+#define CONTROL_ERRMSG "invalid command arguments\n"
+
+
+#endif /* _CONTROLL_H_ */
View
1 fdb.c
@@ -32,6 +32,7 @@ void
destroy_fdb (struct fdb * fdb)
{
pthread_cancel (fdb->decrease_ttl_t);
+ destroy_hash (&fdb->fdb);
return;
}
View
50 hash.c
@@ -162,6 +162,56 @@ search_hash (struct hash * hash, void * key)
+void
+destroy_hash (struct hash * hash)
+{
+ int n;
+ struct hashnode * ptr, * pptr, * prev;
+
+ for (n = 0; n < HASH_TABLE_SIZE; n++) {
+ ptr = &hash->table[n];
+ if (ptr->next != NULL) {
+ for (pptr = ptr->next; pptr != NULL;) {
+ prev = pptr;
+ pptr = pptr->next;
+ free (prev->key);
+ free (prev->data);
+ }
+ }
+ }
+
+ return;
+}
+
+
+void **
+create_list_from_hash (struct hash * hash, int * num)
+{
+ int n, c;
+ void ** datalist;
+ struct hashnode * ptr, * pptr;
+
+ datalist = (void **) malloc (sizeof (void *) * hash->count);
+ memset (datalist, 0, sizeof (void *) * hash->count);
+
+ for (c = 0, n = 0; n < HASH_TABLE_SIZE; n++) {
+ ptr = &hash->table[n];
+ if (ptr->next != NULL) {
+ for (pptr = ptr->next;
+ pptr != NULL;
+ pptr = pptr->next) {
+ datalist[c] = (void *) malloc (sizeof (void *));
+ datalist[c++] = pptr->data;
+ }
+ }
+ }
+
+ *num = hash->count;
+ return datalist;
+}
+
+
+
#include <stdio.h>
void
View
2 hash.h
@@ -24,7 +24,9 @@ void init_hash (struct hash * hash, int keylen);
int insert_hash (struct hash * hash, void * data, void * key);
void * delete_hash (struct hash * hash, void * key);
void * search_hash (struct hash * hash, void * key);
+void destroy_hash (struct hash * hash);
+void ** create_list_from_hash (struct hash * hash, int * num);
/* debug */
void print_all_hash (struct hash * hash);
View
1 iftap.c
@@ -37,6 +37,7 @@ tap_alloc (char * dev)
return fd;
}
+
int
tap_up (char * dev)
{
View
157 main.c
@@ -1,7 +1,9 @@
-#include <stdio.h>
#include <err.h>
+#include <errno.h>
+#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
+#include <signal.h>
#include <limits.h>
#include <string.h>
#include <net/if.h>
@@ -21,6 +23,7 @@
#include "fdb.h"
#include "iftap.h"
#include "vxlan.h"
+#include "control.h"
struct vxlan vxlan;
@@ -34,37 +37,75 @@ void debug_print_ether (struct ether_header * ether);
void
usage (void)
{
- printf ("Usage\n");
- printf ("\n");
- printf (" vxlan -m [MCASTADDR] -i [INTERFACE] [VNI] [VNI]... ");
- printf ("\n");
- printf ("\t -m : Multicast Address(v4/v6)\n");
- printf ("\t -i : Multicast Interface\n");
- printf ("\t -e : Print Error Massage to STDOUT\n");
- printf ("\t -c : Access List File\n");
- printf ("\t -d : Daemon Mode\n");
- printf ("\n");
+ printf ("\n"
+ " Usage\n"
+ "\n"
+ " vxland -m [MCASTADDR] -i [INTERFACE]"
+ "\n"
+ "\t -m : Multicast Address(v4/v6)\n"
+ "\t -i : Multicast Interface\n"
+ "\t -e : Print Error Massage to STDOUT\n"
+ "\t -d : Daemon Mode\n"
+ "\t -h : Print Usage (this message)\n"
+ "\n"
+ " vxland is forwarding daemon. Please configure using vxlanctl.\n"
+ "\n"
+ );
+
+ return;
+}
+
+void
+cleanup (void)
+{
+ int n, vins_num;
+ struct vxlan_instance ** vins_list;
+
+ /* stop control thread */
+ pthread_cancel (vxlan.control_tid);
+
+ /* stop all vxlan instance */
+ vins_list = (struct vxlan_instance **)
+ create_list_from_hash (&vxlan.vins_tuple, &vins_num);
+
+ for (n = 0; n < vins_num; n++) {
+ destroy_vxlan_instance (vins_list[n]);
+ }
+
+ destroy_hash (&vxlan.vins_tuple);
+
+ /* close sockets */
+ close (vxlan.udp_sock);
+ close (vxlan.unicast_sock);
+ close (vxlan.control_sock);
+
+ return;
+}
+
+void
+sig_cleanup (int signal)
+{
+ cleanup ();
}
int
main (int argc, char * argv[])
{
- int ch, n;
+ int ch;
int d_flag = 0, err_flag = 0;
extern int opterr;
extern char * optarg;
struct addrinfo hints, *res;
- char configfile[48] = "";
char mcast_caddr[40] = "";
char vxlan_if_name[IFNAMSIZ] = "";
- u_int8_t vnibuf[VXLAN_VNISIZE];
memset (&vxlan, 0, sizeof (vxlan));
+ init_hash (&vxlan.vins_tuple, VXLAN_VNISIZE);
- while ((ch = getopt (argc, argv, "em:i:c:n:d")) != -1) {
+ while ((ch = getopt (argc, argv, "ehm:di:")) != -1) {
switch (ch) {
case 'e' :
err_flag = 1;
@@ -84,21 +125,16 @@ main (int argc, char * argv[])
d_flag = 1;
break;
- case 'c' :
- strncpy (configfile, optarg, sizeof (configfile));
- break;
-
+ case 'h' :
+ usage ();
+ return 0;
+
default :
usage ();
return -1;
}
}
- if ((vxlan.vins_num = argc - optind) < 1) {
- usage ();
- error_quit ("Please Set VNI(s)");
- }
-
if (d_flag > 0) {
if (daemon (1, err_flag) < 0)
err (EXIT_FAILURE, "failed to run as a daemon");
@@ -114,7 +150,6 @@ main (int argc, char * argv[])
hints.ai_protocol = IPPROTO_UDP;
if (getaddrinfo (mcast_caddr, VXLAN_CPORT, &hints, &res) != 0) {
- usage ();
error_quit ("Invalid Multicast Address \"%s\"", mcast_caddr);
}
@@ -156,39 +191,8 @@ main (int argc, char * argv[])
((struct sockaddr_in *)&vxlan.mcast_addr)->sin_port = htons (vxlan.port);
-#if 0
- /* Create Unicast Socket */
- if ((vxlan.unicast_sock = socket (EXTRACT_FAMILY(vxlan.mcast_addr),
- SOCK_DGRAM,
- IPPROTO_UDP)) < 0)
- err (EXIT_FAILURE, "can not create unicast socket");
-
- struct sockaddr_storage sa_str;
- memset (&sa_str, 0, sizeof (sa_str));
- EXTRACT_PORT (sa_str) = htons (VXLAN_PORT_BASE);
-
- if (bind (vxlan.unicast_sock, (struct sockaddr *)&sa_str, sizeof (sa_str)) < 0)
- err (EXIT_FAILURE, "can not bind udp socket");
-#endif
-
-
- /* Create vxlan tap interface instance(s) */
-
- init_hash (&vxlan.vins_tuple, VXLAN_VNISIZE);
-
-
- vxlan.vins = (struct vxlan_instance **)
- malloc (sizeof (struct vxlan_instance) * vxlan.vins_num);
-
- for (n = 0; n < vxlan.vins_num; n++) {
- strtovni (argv[optind + n], vnibuf);
- vxlan.vins[n] = (struct vxlan_instance *)
- malloc (sizeof (struct vxlan_instance *));
- vxlan.vins[n] = create_vxlan_instance (vnibuf, configfile);
- insert_hash (&vxlan.vins_tuple, vxlan.vins[n], vnibuf);
- init_vxlan_instance (vxlan.vins[n]);
- }
-
+ /* Start Control Thread */
+ init_vxlan_control ();
/* Enable syslog */
if (err_flag == 0) {
@@ -200,11 +204,17 @@ main (int argc, char * argv[])
}
+ /* set signal handler */
+ if (atexit (cleanup) < 0)
+ err (EXIT_FAILURE, "failed to register exit hook");
+
+ if (signal (SIGINT, sig_cleanup) == SIG_ERR)
+ err (EXIT_FAILURE, "failed to register SIGINT hook");
+
process_vxlan ();
- /* not reached */
- return -1;
+ return 0;
}
@@ -223,34 +233,37 @@ process_vxlan (void)
memset (buf, 0, sizeof (buf));
+ /* From Internet */
while (1) {
+
FD_ZERO (&fds);
FD_SET (vxlan.udp_sock, &fds);
- memset (&sa_str, 0, sizeof (sa_str));
- if (select (vxlan.udp_sock + 1, &fds, NULL, NULL, NULL) < 0)
- err (EXIT_FAILURE, "select failed");
-
- /* From Internet */
- if ((len = recvfrom (vxlan.udp_sock, buf, sizeof (buf), 0,
- (struct sockaddr *)&sa_str, &s_t)) < 0) {
- error_warn ("read from udp socket failed");
- continue;
- }
-
+ pselect (vxlan.udp_sock + 1, &fds, NULL, NULL, NULL, NULL);
+
+ if (!FD_ISSET (vxlan.udp_sock, &fds))
+ break;
+
+ if ((len = recvfrom (vxlan.udp_sock, buf, sizeof (buf), 0,
+ (struct sockaddr *)&sa_str, &s_t)) < 0)
+ break;
+
+ memset (&sa_str, 0, sizeof (sa_str));
+
vhdr = (struct vxlan_hdr *) buf;
if ((vins = search_hash (&vxlan.vins_tuple, vhdr->vxlan_vni)) == NULL) {
error_warn ("invalid VNI %02x%02x%02x",
vhdr->vxlan_vni[0],
vhdr->vxlan_vni[1],
vhdr->vxlan_vni[2]);
- continue;
+ break;
}
ether = (struct ether_header *) (buf + sizeof (struct vxlan_hdr));
process_fdb_etherflame_from_vxlan (vins, ether, &sa_str);
send_etherflame_from_vxlan_to_local (vins, ether,
len - sizeof (struct vxlan_hdr));
+
}
return;
View
15 makefile
@@ -3,19 +3,22 @@
CC = gcc -Wall -g -DLOGGING_FDB_CHANGE
-MODULES = error.o fdb.o hash.o iftap.o net.o vxlan.o
-PROGNAME = vxlan
+MODULES = error.o fdb.o hash.o iftap.o net.o vxlan.o control.o
+PROGNAME = vxland vxlanctl
.PHONY : all
-all : modules vxlan
+all : modules vxland vxlanctl
.c.o:
$(CC) -c $< -o $@
modules : $(MODULES)
-vxlan : main.c common.h $(MODULES)
- $(CC) -lpthread main.c $(MODULES) -o vxlan
+vxland : main.c common.h $(MODULES)
+ $(CC) -lpthread main.c $(MODULES) -o vxland
+
+vxlanctl : vxlanctl.c common.h
+ $(CC) vxlanctl.c -o vxlanctl
clean :
- rm $(MODULES) vxlan
+ rm $(MODULES) $(PROGNAME)
View
5 net.h
@@ -7,17 +7,12 @@
#include "common.h"
-void process_fdb_etherflame_from_vxlan (struct vxlan_instance * vins,
- struct ether_header * ether,
- struct sockaddr_storage * vtep_addr);
-
void send_etherflame_from_vxlan_to_local (struct vxlan_instance * vins,
struct ether_header * ether, int len);
void send_etherflame_from_local_to_vxlan (struct vxlan_instance * vins,
struct ether_header * ether, int len);
-
struct in_addr getifaddr (char * dev);
struct in6_addr getifaddr6 (char * dev);
int ifaddr (int ai_family, char * dev, void * dest);
View
181 vxlan.c
@@ -1,4 +1,5 @@
#include <err.h>
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -19,88 +20,6 @@
void * process_vxlan_instance (void * param);
-/* access list related type */
-
-#define ACL_TYPE_MAC 0
-#define ACL_TYPE_IP4 1
-#define ACL_TYPE_IP6 2
-#define ACL_TYPE_RA 3
-#define ACL_TYPE_RS 4
-
-struct acl_entry {
- int type;
- u_int8_t vni[VXLAN_VNISIZE];
-
- union {
- u_int8_t mac[ETH_ALEN];
- struct in_addr addr4;
- struct in6_addr addr6;
- } term;
-};
-#define term_mac term.mac
-#define term_ip4 term.addr4
-#define term_ip6 term.addr6
-
-
-int
-strtoaclentry (char * str, struct acl_entry * e)
-{
- char type[16];
- char cvni[16];
- char addr[48];
- int mac[ETH_ALEN];
- struct acl_entry entry;
-
- if (sscanf (str, "%s %s %s", type, cvni, addr) < 3)
- return -1;
-
- if (type[0] == '#' || type[0] == ' ')
- return -1;
-
- strtovni (cvni, entry.vni);
-
- if (strncmp (type, "mac", 3) == 0) {
- if (sscanf (addr, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1],
- &mac[2], &mac[3], &mac[4], &mac[5]) < 6)
- return -1;
-
- entry.type = ACL_TYPE_MAC;
- entry.term_mac[0] = mac[0];
- entry.term_mac[1] = mac[1];
- entry.term_mac[2] = mac[2];
- entry.term_mac[3] = mac[3];
- entry.term_mac[4] = mac[4];
- entry.term_mac[5] = mac[5];
-
- memcpy (e, &entry, sizeof (entry));
- return ACL_TYPE_MAC;
-
- } else if (strncmp (type, "ns", 2) == 0) {
- entry.type = ACL_TYPE_IP6;
- if (inet_pton (AF_INET6, addr, &entry.term_ip6) < 1)
- return -1;
-
- memcpy (e, &entry, sizeof (entry));
- return ACL_TYPE_IP6;
-
- } else if (strncmp (type, "arp", 3) == 0) {
- entry.type = ACL_TYPE_IP4;
- if (inet_pton (AF_INET, addr, &entry.term_ip4) < 1)
- return -1;
-
- memcpy (e, &entry, sizeof (entry));
- return ACL_TYPE_IP4;
- } else if (strncmp (type, "ra", 2) == 0) {
- return ACL_TYPE_RA;
- } else if (strncmp (type, "rs", 2) == 0) {
- return ACL_TYPE_RS;
- }
-
- return -1;
-}
-
-
-
void
strtovni (char * str, u_int8_t * vni)
{
@@ -125,15 +44,11 @@ strtovni (char * str, u_int8_t * vni)
struct vxlan_instance *
-create_vxlan_instance (u_int8_t * vni, char * configfile)
+create_vxlan_instance (u_int8_t * vni)
{
- int type;
char cbuf[16];
- char buf[1024];
- FILE * cfp;
u_int32_t vni32;
struct vxlan_instance * vins;
- struct acl_entry ae, * e;
/* create socket and fdb */
vins = (struct vxlan_instance *) malloc (sizeof (struct vxlan_instance));
@@ -155,54 +70,9 @@ create_vxlan_instance (u_int8_t * vni, char * configfile)
init_hash (&vins->acl_ip4, sizeof (struct in_addr));
init_hash (&vins->acl_ip6, sizeof (struct in6_addr));
- if (configfile == NULL || configfile[0] == '\0')
- return vins;
-
- if ((cfp = fopen (configfile, "r")) == NULL)
- err (EXIT_FAILURE, "can not open config file \"%s\"", configfile);
-
- while (fgets (buf, sizeof (buf), cfp)) {
- if ((type = strtoaclentry (buf, &ae)) < 0)
- continue;
-
- if (CHECK_VNI (vins->vni, ae.vni) < 0)
- continue;
-
- e = (struct acl_entry *) malloc (sizeof (ae));
- memcpy (e, &ae, sizeof (ae));
-
- switch (type) {
- case ACL_TYPE_MAC :
- insert_hash (&vins->acl_mac, e, &e->term_mac);
- printf ("insert mac\n");
- break;
- case ACL_TYPE_IP4 :
- insert_hash (&vins->acl_ip4, e, &e->term_ip4);
- break;
- case ACL_TYPE_IP6 :
- insert_hash (&vins->acl_ip6, e, &e->term_ip6);
- printf ("insert ipv6\n");
- break;
- case ACL_TYPE_RA :
- vins->acl_mask |= ACL_MASK_RA;
- printf ("out bound RA Block\n");
- break;
- case ACL_TYPE_RS :
- vins->acl_mask |= ACL_MASK_RS;
- printf ("out bound RS Block\n");
- break;
-
- default :
- continue;
- }
- }
-
- fclose (cfp);
-
return vins;
}
-
void
init_vxlan_instance (struct vxlan_instance * vins)
{
@@ -217,6 +87,37 @@ init_vxlan_instance (struct vxlan_instance * vins)
return;
}
+int
+destroy_vxlan_instance (struct vxlan_instance * vins)
+{
+ /* error handling */
+ if (vxlan.vins_num < 1) {
+ return -1;
+ }
+
+ if (vins == NULL) {
+ error_warn ("%s: vxlan_instance is NULL!!", __func__);
+ return -1;
+ }
+
+ /* Stop And Delete */
+ if (pthread_cancel (vins->tid) != 0)
+ error_warn ("%s: can not stop vxlan instance %s", vins->vxlan_tap_name);
+
+ if (close (vins->tap_sock) < 0)
+ error_warn ("%s: can not close tap socket %s : %s",
+ vins->vxlan_tap_name,
+ strerror (errno));
+
+ destroy_fdb (vins->fdb);
+
+ /* cleaning struct vxlan values */
+ vxlan.vins_num--;
+ delete_hash (&vxlan.vins_tuple, vins->vni);
+
+ return 0;
+}
+
void
process_fdb_etherflame_from_vxlan (struct vxlan_instance * vins,
struct ether_header * ether,
@@ -257,7 +158,6 @@ process_vxlan_instance (void * param)
{
int len;
char buf[VXLAN_PACKET_BUF_LEN];
- fd_set fds;
struct vxlan_instance * vins;
vins = (struct vxlan_instance *) param;
@@ -268,19 +168,8 @@ process_vxlan_instance (void * param)
printf ("SOCKET : %d\n", vins->tap_sock);
#endif
- while (1) {
- FD_ZERO (&fds);
- FD_SET (vins->tap_sock, &fds);
-
- if (select (vins->tap_sock + 1, &fds, NULL, NULL, NULL) < 0)
- err (EXIT_FAILURE, "select failed : %s", vins->vxlan_tap_name);
-
- /* From Tap */
- if ((len = read (vins->tap_sock, buf, sizeof (buf))) < 0) {
- error_warn ("read from tap failed");
- continue;
- }
-
+ /* From Tap */
+ while ((len = read (vins->tap_sock, buf, sizeof (buf))) < 0) {
send_etherflame_from_local_to_vxlan (vins,
(struct ether_header * )buf,
len);
View
16 vxlan.h
@@ -1,22 +1,22 @@
#ifndef _VXLAN_H_
#define _VXLAN_H_
+#include <net/ethernet.h>
+
+
#include "common.h"
+
+
void strtovni (char * str, u_int8_t * vni);
-struct vxlan_instance * create_vxlan_instance (u_int8_t * vni, char * configfile);
+
+struct vxlan_instance * create_vxlan_instance (u_int8_t * vni);
void init_vxlan_instance (struct vxlan_instance * vins);
+int destroy_vxlan_instance (struct vxlan_instance * vins);
void process_fdb_etherflame_from_vxlan (struct vxlan_instance * vins,
struct ether_header * ether,
struct sockaddr_storage * vtep_addr);
-void send_etherflame_from_vxlan_to_local (struct vxlan_instance * vins,
- struct ether_header * ether, int len);
-
-void send_etherflame_from_local_to_vxlan (struct vxlan_instance * vins,
- struct ether_header * ether, int len);
-
-
#endif
View
105 vxlanctl.c
@@ -0,0 +1,105 @@
+/* vxlanctl.c */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+
+#include "common.h"
+
+int create_unix_client_socket (char * domain);
+
+
+void
+usage (void)
+{
+ printf ("\n"
+ " Usage :\n"
+ "\t vxlanctl [commands]\n"
+ "\n"
+ " commands: (VNI is hex)\n"
+ "\n"
+ " create <VNI> add vxlan interface\n"
+ " destroy <VNI> delete vxlan interface\n"
+ " acl <VNI> mac [deny|permit] <Mac Addr> Source Mac Address Filter\n"
+ " acl <VNI> arp [deny|permit] <v4Addr> ARP Target Address Filter\n"
+ " acl <VNI> ns [deny|permit] <v6Addr> NS Target Address Filter\n"
+ " acl <VNI> ra [deny|permit] RA Filter\n"
+ " acl <VNI> rs [deny|permit] RS FIlter\n"
+ "\n"
+ "\n"
+ " !! All Access List is Outbound Filter !!\n"
+ "\n"
+ );
+
+ return;
+}
+
+int
+main (int argc, char * argv[])
+{
+ int n, sock;
+ char cmdstr[512], resstr[512], buf[512];
+
+ if (argc < 2) {
+ usage ();
+ return 0;
+ }
+
+ if (strcmp (argv[1], "-h") == 0 ||
+ strcmp (argv[1], "--help") == 0) {
+ usage ();
+ return 0;
+ }
+
+ memset (cmdstr, 0, sizeof (cmdstr));
+ memset (resstr, 0, sizeof (resstr));
+
+ for (n = 1; n < argc; n++) {
+ strncpy (buf, cmdstr, sizeof (buf));
+ snprintf (cmdstr, sizeof (cmdstr), "%s %s", buf, argv[n]);
+ }
+
+ sock = create_unix_client_socket (VXLAN_UNIX_DOMAIN);
+
+ if (write (sock, cmdstr, strlen (cmdstr)) < 0) {
+ perror ("write");
+ shutdown (sock, SHUT_RDWR);
+ close (sock);
+ }
+
+ if (read (sock, resstr, sizeof (resstr)) < 0) {
+ perror ("read");
+ shutdown (sock, SHUT_RDWR);
+ close (sock);
+ }
+
+ printf ("%s", resstr);
+
+ return 0;
+}
+
+
+int
+create_unix_client_socket (char * domain)
+{
+ int sock;
+ struct sockaddr_un saddru;
+
+ memset (&saddru, 0, sizeof (saddru));
+ saddru.sun_family = AF_UNIX;
+ strncpy (saddru.sun_path, domain, UNIX_PATH_MAX);
+
+ if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ err (EXIT_FAILURE, "can not create unix socket");
+
+ if (connect (sock, (struct sockaddr *)&saddru, sizeof (saddru)) != 0)
+ err (EXIT_FAILURE, "can not connect to unix socket \"%s\"", domain);
+
+ return sock;
+}

0 comments on commit 9040ce2

Please sign in to comment.