summaryrefslogtreecommitdiff
path: root/zebra/zserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r--zebra/zserv.c138
1 files changed, 132 insertions, 6 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 9beae9232e..fb02d60ba4 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1013,6 +1013,28 @@ zsend_router_id_update (struct zserv *client, struct prefix *p,
return zebra_server_send_message(client);
}
+/*
+ * Function used by Zebra to send a PW status update to LDP daemon
+ */
+int
+zsend_pw_update (struct zserv *client, struct zebra_pw *pw)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset (s);
+
+ zserv_create_header (s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
+ stream_write (s, pw->ifname, IF_NAMESIZE);
+ stream_putl (s, pw->ifindex);
+ stream_putl (s, pw->status);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ return zebra_server_send_message (client);
+}
+
/* Register zebra server interface information. Send current all
interface and address information. */
static int
@@ -1762,16 +1784,14 @@ zread_mpls_labels (int command, struct zserv *client, u_short length,
{
mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate,
NULL, ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
- distance, out_label);
+ mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
}
else if (command == ZEBRA_MPLS_LABELS_DELETE)
{
mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, NULL, ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
- distance, out_label);
+ mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
}
}
/* Send response to a label manager connect request to client */
@@ -1933,6 +1953,103 @@ zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id)
}
}
+static int
+zread_pseudowire (int command, struct zserv *client, u_short length,
+ vrf_id_t vrf_id)
+{
+ struct stream *s;
+ struct zebra_vrf *zvrf;
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ uint8_t protocol;
+ struct zebra_pw *pw;
+
+ zvrf = vrf_info_lookup (vrf_id);
+ if (!zvrf)
+ return -1;
+
+ /* Get input stream. */
+ s = client->ibuf;
+
+ /* Get data. */
+ stream_get (ifname, s, IF_NAMESIZE);
+ ifindex = stream_getl (s);
+ type = stream_getl (s);
+ af = stream_getl (s);
+ switch (af)
+ {
+ case AF_INET:
+ nexthop.ipv4.s_addr = stream_get_ipv4 (s);
+ break;
+ case AF_INET6:
+ stream_get (&nexthop.ipv6, s, 16);
+ break;
+ default:
+ return -1;
+ }
+ local_label = stream_getl (s);
+ remote_label = stream_getl (s);
+ flags = stream_getc (s);
+ stream_get (&data, s, sizeof(data));
+ protocol = client->proto;
+
+ pw = zebra_pw_find(zvrf, ifname);
+ switch (command)
+ {
+ case ZEBRA_PW_ADD:
+ if (pw)
+ {
+ zlog_warn ("%s: pseudowire %s already exists [%s]", __func__, ifname,
+ zserv_command_string (command));
+ return -1;
+ }
+
+ zebra_pw_add (zvrf, ifname, protocol, client);
+ break;
+ case ZEBRA_PW_DELETE:
+ if (!pw)
+ {
+ zlog_warn ("%s: pseudowire %s not found [%s]", __func__, ifname,
+ zserv_command_string (command));
+ return -1;
+ }
+
+ zebra_pw_del (zvrf, pw);
+ break;
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ if (!pw)
+ {
+ zlog_warn ("%s: pseudowire %s not found [%s]", __func__, ifname,
+ zserv_command_string (command));
+ return -1;
+ }
+
+ switch (command)
+ {
+ case ZEBRA_PW_SET:
+ pw->enabled = 1;
+ break;
+ case ZEBRA_PW_UNSET:
+ pw->enabled = 0;
+ break;
+ }
+
+ zebra_pw_change (pw, ifindex, type, af, &nexthop, local_label,
+ remote_label, flags, &data);
+ break;
+ }
+
+ return 0;
+}
+
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
static void
zebra_client_close_cleanup_rnh (struct zserv *client)
@@ -1972,6 +2089,9 @@ zebra_client_close (struct zserv *client)
/* Release Label Manager chunks */
release_daemon_chunks (client->proto, client->instance);
+ /* Remove pseudowires associated with this client */
+ zebra_pw_client_close (client);
+
/* Close file descriptor. */
if (client->sock)
{
@@ -2269,6 +2389,12 @@ zebra_client_read (struct thread *thread)
case ZEBRA_RELEASE_LABEL_CHUNK:
zread_label_manager_request (command, client, vrf_id);
break;
+ case ZEBRA_PW_ADD:
+ case ZEBRA_PW_DELETE:
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ zread_pseudowire (command, client, length, vrf_id);
+ break;
default:
zlog_info ("Zebra received unknown command %d", command);
break;