diff options
Diffstat (limited to 'zebra/zserv.c')
| -rw-r--r-- | zebra/zserv.c | 131 |
1 files changed, 125 insertions, 6 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c index aac3d23a9e..bdb7755b63 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1085,6 +1085,27 @@ int 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 zread_interface_add(struct zserv *client, u_short length, @@ -1877,14 +1898,12 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length, if (command == ZEBRA_MPLS_LABELS_ADD) { mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate, 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, 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 */ @@ -2039,6 +2058,97 @@ static void zread_label_manager_request(int cmd, struct zserv *client, } } +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) { @@ -2083,6 +2193,9 @@ static void zebra_client_close(struct zserv *client) zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT), client); + /* Remove pseudowires associated with this client */ + zebra_pw_client_close(client); + /* Close file descriptor. */ if (client->sock) { unsigned long nroutes; @@ -2436,6 +2549,12 @@ static int zebra_client_read(struct thread *thread) case ZEBRA_INTERFACE_SET_MASTER: zread_interface_set_master(client, sock, length); 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; |
