summaryrefslogtreecommitdiff
path: root/zebra/zebra_mpls_openbsd.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-08-08 07:54:32 -0400
committerGitHub <noreply@github.com>2017-08-08 07:54:32 -0400
commitf66e92bc4856352dc4c1c81fa35b1dd570cd83e5 (patch)
treed95a4b505cc238c09ea4d2512f2ad6af92f5cb9c /zebra/zebra_mpls_openbsd.c
parent78986c05cdb4adf6019d02dc328341943c573b35 (diff)
parent1a99ca998dd05c41d4068ace4ca3ef8ac4ba309c (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.c100
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;
}