int zclient_send_linkmetrics_subscribe (struct zclient *zclient, uint16_t cmd) { struct stream *s; if (zclient->sock < 0) { zlog_err ("%s: not connected to zebra", __func__); return -1; } s = zclient->obuf; stream_reset (s); zclient_create_header (s, cmd); stream_putw_at (s, 0, stream_get_endp (s)); if (zclient_send_message (zclient)) { zlog_err ("%s: zclient_send_message() failed", __func__); return -1; } return 0; }
/* * "xdr_encode"-like interface that allows daemon (client) to send * a message to zebra server for a route that needs to be * added/deleted to the kernel. Info about the route is specified * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes * the info down the zclient socket using the stream_* functions. * * The corresponding read ("xdr_decode") function on the server * side is zread_ipv4_add()/zread_ipv4_delete(). * * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Length (2) | Command | Route Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ZEBRA Flags | Message Flags | Prefix length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Destination IPv4 Prefix for route | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nexthop count | * +-+-+-+-+-+-+-+-+ * * * A number of IPv4 nexthop(s) or nexthop interface index(es) are then * described, as per the Nexthop count. Each nexthop described as: * * +-+-+-+-+-+-+-+-+ * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv4 Nexthop address or Interface Index number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ * nexthop information is provided, and the message describes a prefix * to blackhole or reject route. * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. * * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 * byte value. * * XXX: No attention paid to alignment. */ int zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, struct zapi_ipv4 *api) { int i; int psize; struct stream *s; /* Reset stream. */ s = zclient->obuf; stream_reset (s); zclient_create_header (s, cmd); /* Put type and nexthop. */ stream_putc (s, api->type); stream_putc (s, api->flags); stream_putc (s, api->message); stream_putw (s, api->safi); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) { if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { stream_putc (s, 1); stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } else stream_putc (s, api->nexthop_num + api->ifindex_num); for (i = 0; i < api->nexthop_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, api->nexthop[i]); } for (i = 0; i < api->ifindex_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); stream_putl (s, api->ifindex[i]); } } if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); }
/* Send simple Zebra message. */ static int zebra_message_send (struct zclient *zclient, int command) { struct stream *s; /* Get zclient output buffer. */ s = zclient->obuf; stream_reset (s); /* Send very simple command only Zebra message. */ zclient_create_header (s, command); return zclient_send_message(zclient); }
/* * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will * then set/unset redist[type] in the client handle (a struct zserv) for the * sending client */ int zebra_redistribute_send (int command, struct zclient *zclient, int type) { struct stream *s; s = zclient->obuf; stream_reset(s); zclient_create_header (s, command); stream_putc (s, type); stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); }
static int zebra_hello_send (struct zclient *zclient) { struct stream *s; if (zclient->redist_default) { s = zclient->obuf; stream_reset (s); zclient_create_header (s, ZEBRA_HELLO); stream_putc (s, zclient->redist_default); stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); } return 0; }
static int zebra_hello_send (struct zclient *zclient) { struct stream *s; if (zclient->redist_default) { s = zclient->obuf; stream_reset (s); /* The VRF ID in the HELLO message is always 0. */ zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT); stream_putc (s, zclient->redist_default); stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); } return 0; }
void ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) { u_char message; u_char distance; u_char flags; int psize; struct stream *s; struct ospf_path *path; struct listnode *node; if (zclient->redist[ZEBRA_ROUTE_OSPF]) { message = 0; flags = 0; /* OSPF pass nexthop and metric */ SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); /* Distance value. */ distance = ospf_distance_apply (p, or); if (distance) SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); /* Make packet. */ s = zclient->obuf; stream_reset (s); /* Put command, type, flags, message. */ zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD); stream_putc (s, ZEBRA_ROUTE_OSPF); stream_putc (s, flags); stream_putc (s, message); stream_putw (s, SAFI_UNICAST); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop count. */ stream_putc (s, or->paths->count); /* Nexthop, ifindex, distance and metric information. */ for (ALL_LIST_ELEMENTS_RO (or->paths, node, path)) { if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX); stream_put_in_addr (s, &path->nexthop); stream_putl (s, path->ifindex); } else if (path->nexthop.s_addr != INADDR_ANY) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, &path->nexthop); } else { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); if (path->ifindex) stream_putl (s, path->ifindex); else stream_putl (s, 0); } if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra: Route add %s/%d nexthop %s", inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, &path->nexthop, buf[1], sizeof(buf[1]))); } } if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, distance); if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) { if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) stream_putl (s, or->cost + or->u.ext.type2_cost); else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) stream_putl (s, or->u.ext.type2_cost); else stream_putl (s, or->cost); } stream_putw_at (s, 0, stream_get_endp (s)); zclient_send_message(zclient); }
static void isis_zebra_route_add_ipv4 (struct prefix *prefix, struct isis_route_info *route_info) { u_char message, flags; int psize; struct stream *stream; struct isis_nexthop *nexthop; struct listnode *node; if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC)) return; if (zclient->redist[ZEBRA_ROUTE_ISIS]) { message = 0; flags = 0; SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (message, ZAPI_MESSAGE_METRIC); #if 0 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); #endif stream = zclient->obuf; stream_reset (stream); zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD); /* type */ stream_putc (stream, ZEBRA_ROUTE_ISIS); /* flags */ stream_putc (stream, flags); /* message */ stream_putc (stream, message); /* prefix information */ psize = PSIZE (prefix->prefixlen); stream_putc (stream, prefix->prefixlen); stream_write (stream, (u_char *) & prefix->u.prefix4, psize); stream_putc (stream, listcount (route_info->nexthops)); /* Nexthop, ifindex, distance and metric information */ for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop)) { /* FIXME: can it be ? */ if (nexthop->ip.s_addr != INADDR_ANY) { stream_putc (stream, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (stream, &nexthop->ip); } else { stream_putc (stream, ZEBRA_NEXTHOP_IFINDEX); stream_putl (stream, nexthop->ifindex); } } #if 0 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (stream, route_info->depth); #endif if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) stream_putl (stream, route_info->cost); stream_putw_at (stream, 0, stream_get_endp (stream)); zclient_send_message(zclient); SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC); }
/* * "xdr_encode"-like interface that allows daemon (client) to send * a message to zebra server for a route that needs to be * added/deleted to the kernel. Info about the route is specified * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes * the info down the zclient socket using the stream_* functions. * * The corresponding read ("xdr_decode") function on the server * side is zread_ipv4_add()/zread_ipv4_delete(). * * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Length (2) | Command | Route Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ZEBRA Flags | Message Flags | Prefix length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Destination IPv4 Prefix for route | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nexthop count | * +-+-+-+-+-+-+-+-+ * * * A number of IPv4 nexthop(s) or nexthop interface index(es) are then * described, as per the Nexthop count. Each nexthop described as: * * +-+-+-+-+-+-+-+-+ * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv4 Nexthop address or Interface Index number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ * nexthop information is provided, and the message describes a prefix * to blackhole or reject route. * * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*() * infrastructure was built around the traditional (32-bit "gate OR * ifindex") nexthop data unit. A special encoding can be used to feed * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route() * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4 * fields as follows: * - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK * - .nexthop_num == .ifindex_num * - .nexthop and .ifindex are filled with gate and ifindex parts of * each compound nexthop, both in the same order * * zapi_ipv4_route() will produce two nexthop data units for each such * interleaved 64-bit nexthop. On the zserv side of the socket it will be * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure. * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. * * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 * byte value. * * XXX: No attention paid to alignment. */ int zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, struct zapi_ipv4 *api) { int i; int psize; struct stream *s; /* Reset stream. */ s = zclient->obuf; stream_reset (s); zclient_create_header (s, cmd); /* Put type and nexthop. */ stream_putc (s, api->type); stream_putc (s, api->flags); stream_putc (s, api->message); stream_putw (s, api->safi); /* Put prefix information. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop, ifindex, distance and metric information. */ /* ZAPI_MESSAGE_ONLINK implies interleaving */ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_ONLINK)) { /* ZAPI_MESSAGE_NEXTHOP is required for proper receiving */ assert (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)); /* 64-bit data units, interleaved between nexthop[] and ifindex[] */ assert (api->nexthop_num == api->ifindex_num); stream_putc (s, api->nexthop_num * 2); for (i = 0; i < api->nexthop_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IPV4_ONLINK); stream_put_in_addr (s, api->nexthop[i]); stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); stream_putl (s, api->ifindex[i]); } } else if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) { /* traditional 32-bit data units */ if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE | ZEBRA_FLAG_REJECT)) { stream_putc (s, 1); stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); /* XXX assert(api->nexthop_num == 0); */ /* XXX assert(api->ifindex_num == 0); */ } else stream_putc (s, api->nexthop_num + api->ifindex_num); for (i = 0; i < api->nexthop_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IPV4); stream_put_in_addr (s, api->nexthop[i]); } for (i = 0; i < api->ifindex_num; i++) { stream_putc (s, ZEBRA_NEXTHOP_IFINDEX); stream_putl (s, api->ifindex[i]); } } if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); return zclient_send_message(zclient); }