]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add support to openbsd's mpw(4) for pseudowires
authorRenato Westphal <renato@opensourcerouting.org>
Fri, 30 Jun 2017 15:18:21 +0000 (12:18 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Tue, 25 Jul 2017 03:53:23 +0000 (00:53 -0300)
Thanks to rzalamena@ for writing mpw(4) :)

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
zebra/zebra_mpls_openbsd.c

index 5dfe16caf54462e539fb64fc0136e5c4b6609889..0fcd28e0eeb04e70ee7011393fa2cff444e63146 100644 (file)
@@ -35,6 +35,7 @@ extern struct zebra_privs_t zserv_privs;
 struct {
   u_int32_t rtseq;
   int fd;
+  int ioctl_fd;
 } kr_state;
 
 static int
@@ -337,6 +338,90 @@ kernel_del_lsp (zebra_lsp_t *lsp)
   return ret;
 }
 
+static int
+kmpw_install (struct zebra_pw *pw)
+{
+  struct ifreq ifr;
+  struct ifmpwreq imr;
+  struct sockaddr_storage ss;
+  struct sockaddr_in *sa_in = (struct sockaddr_in *) &ss;
+  struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) &ss;
+
+  memset (&imr, 0, sizeof (imr));
+  switch (pw->type)
+    {
+    case PW_TYPE_ETHERNET:
+      imr.imr_type = IMR_TYPE_ETHERNET;
+      break;
+    case PW_TYPE_ETHERNET_TAGGED:
+      imr.imr_type = IMR_TYPE_ETHERNET_TAGGED;
+      break;
+    default:
+      zlog_err ("%s: unhandled pseudowire type (%#X)", __func__,
+                pw->type);
+      return -1;
+    }
+
+  if (pw->flags & F_PSEUDOWIRE_CWORD)
+    imr.imr_flags |= IMR_FLAG_CONTROLWORD;
+
+  /* pseudowire nexthop */
+  memset (&ss, 0, sizeof (ss));
+  switch (pw->af) {
+    case AF_INET:
+      sa_in->sin_family = AF_INET;
+      sa_in->sin_len = sizeof (struct sockaddr_in);
+      sa_in->sin_addr = pw->nexthop.ipv4;
+      break;
+    case AF_INET6:
+      sa_in6->sin6_family = AF_INET6;
+      sa_in6->sin6_len = sizeof (struct sockaddr_in6);
+      sa_in6->sin6_addr = pw->nexthop.ipv6;
+      break;
+    default:
+      zlog_err ("%s: unhandled pseudowire address-family (%u)", __func__,
+               pw->af);
+      return -1;
+  }
+  memcpy (&imr.imr_nexthop, (struct sockaddr *) &ss,
+         sizeof (imr.imr_nexthop));
+
+  /* pseudowire local/remote labels */
+  imr.imr_lshim.shim_label = pw->local_label;
+  imr.imr_rshim.shim_label = pw->remote_label;
+
+  /* ioctl */
+  memset (&ifr, 0, sizeof (ifr));
+  strlcpy (ifr.ifr_name, pw->ifname, sizeof (ifr.ifr_name));
+  ifr.ifr_data = (caddr_t) &imr;
+  if (ioctl (kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1)
+    {
+      zlog_err ("ioctl SIOCSETMPWCFG: %s", safe_strerror (errno));
+      return -1;
+    }
+
+  return 0;
+}
+
+static int
+kmpw_uninstall (struct zebra_pw *pw)
+{
+  struct ifreq ifr;
+  struct ifmpwreq imr;
+
+  memset(&ifr, 0, sizeof (ifr));
+  memset(&imr, 0, sizeof (imr));
+  strlcpy (ifr.ifr_name, pw->ifname, sizeof (ifr.ifr_name));
+  ifr.ifr_data = (caddr_t) &imr;
+  if (ioctl (kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1)
+    {
+      zlog_err ("ioctl SIOCSETMPWCFG: %s", safe_strerror (errno));
+      return -1;
+    }
+
+  return 0;
+}
+
 #define MAX_RTSOCK_BUF 128 * 1024
 int
 mpls_kernel_init (void)
@@ -344,10 +429,17 @@ mpls_kernel_init (void)
   int          rcvbuf, default_rcvbuf;
   socklen_t    optlen;
 
-  if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
+  if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1)
+    {
       zlog_warn("%s: socket", __func__);
       return -1;
-  }
+    }
+
+  if ((kr_state.ioctl_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1)
+    {
+      zlog_warn("%s: ioctl socket", __func__);
+      return -1;
+    }
 
   /* grow receive buffer, don't wanna miss messages */
   optlen = sizeof (default_rcvbuf);
@@ -364,5 +456,9 @@ mpls_kernel_init (void)
 
   kr_state.rtseq = 1;
 
+  /* register hook to install/uninstall pseudowires */
+  hook_register (pw_install, kmpw_install);
+  hook_register (pw_uninstall, kmpw_uninstall);
+
   return 0;
 }