]> git.puffer.fish Git - matthieu/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)
committerDavid Lamparter <equinox@opensourcerouting.org>
Wed, 9 Aug 2017 10:35:16 +0000 (12:35 +0200)
Thanks to rzalamena@ for writing mpw(4) :)

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

index c3d09aedbd5022977c25047d98b3328da1e95586..119cd5b700c2aa62bebc1675cc81fa6eeda1c0ae 100644 (file)
@@ -37,6 +37,7 @@ extern struct zebra_privs_t zserv_privs;
 struct {
        u_int32_t rtseq;
        int fd;
+       int ioctl_fd;
 } kr_state;
 
 static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
@@ -330,6 +331,85 @@ int 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)
 {
@@ -341,6 +421,12 @@ int mpls_kernel_init(void)
                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);
        if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
@@ -359,6 +445,10 @@ int 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;
 }