diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-08-08 07:54:32 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-08 07:54:32 -0400 |
| commit | f66e92bc4856352dc4c1c81fa35b1dd570cd83e5 (patch) | |
| tree | d95a4b505cc238c09ea4d2512f2ad6af92f5cb9c /zebra/zebra_mpls_openbsd.c | |
| parent | 78986c05cdb4adf6019d02dc328341943c573b35 (diff) | |
| parent | 1a99ca998dd05c41d4068ace4ca3ef8ac4ba309c (diff) | |
Merge pull request #783 from opensourcerouting/pw-manager-2
Add Pseudowire management in Zebra
Diffstat (limited to 'zebra/zebra_mpls_openbsd.c')
| -rw-r--r-- | zebra/zebra_mpls_openbsd.c | 100 |
1 files changed, 98 insertions, 2 deletions
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 5dfe16caf5..0fcd28e0ee 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -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; } |
