#include "linklist.h"
#include "link_state.h"
#include "cspf.h"
+#include "tc.h"
#include "sharpd/sharp_globals.h"
#include "sharpd/sharp_zebra.h"
return CMD_SUCCESS;
}
+DEFPY (tc_filter_rate,
+ tc_filter_rate_cmd,
+ "sharp tc dev IFNAME$ifname \
+ source <A.B.C.D/M|X:X::X:X/M>$src \
+ destination <A.B.C.D/M|X:X::X:X/M>$dst \
+ ip-protocol <tcp|udp>$ip_proto \
+ src-port (1-65535)$src_port \
+ dst-port (1-65535)$dst_port \
+ rate RATE$ratestr",
+ SHARP_STR
+ "Traffic control\n"
+ "TC interface (for qdisc, class, filter)\n"
+ "TC interface name\n"
+ "TC filter source\n"
+ "TC filter source IPv4 prefix\n"
+ "TC filter source IPv6 prefix\n"
+ "TC filter destination\n"
+ "TC filter destination IPv4 prefix\n"
+ "TC filter destination IPv6 prefix\n"
+ "TC filter IP protocol\n"
+ "TC filter IP protocol TCP\n"
+ "TC filter IP protocol UDP\n"
+ "TC filter source port\n"
+ "TC filter source port\n"
+ "TC filter destination port\n"
+ "TC filter destination port\n"
+ "TC rate\n"
+ "TC rate number (bits/s) or rate string (suffixed with Bps or bit)\n")
+{
+ struct interface *ifp;
+ struct protoent *p;
+ uint64_t rate;
+
+ ifp = if_lookup_vrf_all(ifname);
+
+ if (!ifp) {
+ vty_out(vty, "%% Can't find interface %s\n", ifname);
+ return CMD_WARNING;
+ }
+
+ p = getprotobyname(ip_proto);
+ if (!p) {
+ vty_out(vty, "Unable to convert %s to proto id\n", ip_proto);
+ return CMD_WARNING;
+ }
+
+ if (tc_getrate(ratestr, &rate) != 0) {
+ vty_out(vty, "Unable to convert %s to rate\n", ratestr);
+ return CMD_WARNING;
+ }
+
+ if (sharp_zebra_send_tc_filter_rate(ifp, src, dst, p->p_proto, src_port,
+ dst_port, rate) != 0)
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
void sharp_vty_init(void)
{
install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
install_element(ENABLE_NODE, &sharp_interface_protodown_cmd);
install_element(ENABLE_NODE, &no_sharp_interface_protodown_cmd);
+ install_element(ENABLE_NODE, &tc_filter_rate_cmd);
+
return;
}
#include "nexthop.h"
#include "nexthop_group.h"
#include "link_state.h"
+#include "tc.h"
#include "sharp_globals.h"
#include "sharp_nht.h"
memcpy(api.opaque.data, opaque, api.opaque.length);
}
- if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api)
- == ZCLIENT_SEND_BUFFERED)
+ if (zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api) ==
+ ZCLIENT_SEND_BUFFERED)
return true;
else
return false;
api.instance = instance;
memcpy(&api.prefix, p, sizeof(*p));
- if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api)
- == ZCLIENT_SEND_BUFFERED)
+ if (zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api) ==
+ ZCLIENT_SEND_BUFFERED)
return true;
else
return false;
if (buffered) {
wb.p = *p;
- wb.count = i+1;
+ wb.count = i + 1;
wb.routes = routes;
wb.vrf_id = vrf_id;
wb.instance = instance;
if (installed) {
sg.r.removed_routes = 0;
- sharp_remove_routes_helper(&p, sg.r.vrf_id,
- sg.r.inst, sg.r.total_routes);
+ sharp_remove_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
+ sg.r.total_routes);
}
if (!installed) {
sg.r.installed_routes = 0;
- sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
- sg.r.nhgid, &sg.r.nhop_group,
- &sg.r.backup_nhop_group,
- sg.r.total_routes, sg.r.flags,
- sg.r.opaque);
+ sharp_install_routes_helper(
+ &p, sg.r.vrf_id, sg.r.inst, sg.r.nhgid,
+ &sg.r.nhop_group, &sg.r.backup_nhop_group,
+ sg.r.total_routes, sg.r.flags, sg.r.opaque);
}
}
case SHARP_INSTALL_ROUTES_RESTART:
sharp_install_routes_restart(
&wb.p, wb.count, wb.vrf_id, wb.instance, wb.nhgid,
- wb.nhg, wb.backup_nhg, wb.routes, wb.flags,
- wb.opaque);
+ wb.nhg, wb.backup_nhg, wb.routes, wb.flags, wb.opaque);
return;
case SHARP_DELETE_ROUTES_RESTART:
sharp_remove_routes_restart(&wb.p, wb.count, wb.vrf_id,
enum zapi_route_notify_owner note;
uint32_t table;
- if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e,
- NULL, NULL))
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e, NULL,
+ NULL))
return -1;
switch (note) {
}
if (api_nhg.nexthop_num == 0) {
- zlog_debug("%s: nhg %u not sent: no valid nexthops",
- __func__, id);
+ zlog_debug("%s: nhg %u not sent: no valid nexthops", __func__,
+ id);
is_valid = false;
goto done;
}
command = ZEBRA_NEXTHOP_UNREGISTER;
if (zclient_send_rnh(zclient, command, p, SAFI_UNICAST, connected,
- false, vrf_id)
- == ZCLIENT_SEND_FAILURE)
+ false, vrf_id) == ZCLIENT_SEND_FAILURE)
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
}
int i;
if (api->nexthop_num == 0) {
- zlog_debug(
- " Not installed");
+ zlog_debug(" Not installed");
return 0;
}
zlog_warn("%s: Decode of redistribute failed: %d", __func__,
ZEBRA_REDISTRIBUTE_ROUTE_ADD);
- zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd),
- &api.prefix, zebra_route_string(api.type));
+ zlog_debug("%s: %pFX (%s)", zserv_command_string(cmd), &api.prefix,
+ zebra_route_string(api.type));
sharp_debug_nexthops(&api);
return 0;
}
-static const char *const type2txt[] = { "Generic", "Vertex", "Edge", "Subnet" };
-static const char *const status2txt[] = { "Unknown", "New", "Update",
- "Delete", "Sync", "Orphan"};
+static const char *const type2txt[] = {"Generic", "Vertex", "Edge", "Subnet"};
+static const char *const status2txt[] = {"Unknown", "New", "Update",
+ "Delete", "Sync", "Orphan"};
/* Handler for opaque messages */
static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
{
status2txt[lse->status],
type2txt[lse->type]);
lse->status = SYNC;
- }
- else
+ } else
zlog_debug(
"%s: Error to convert Stream into Link State",
__func__);
instance, session_id,
buf, sizeof(buf));
if (ret == ZCLIENT_SEND_FAILURE) {
- zlog_debug("%s: send_opaque() failed => %d",
- __func__, ret);
+ zlog_debug("%s: send_opaque() failed => %d", __func__,
+ ret);
break;
}
}
-
}
/*
stream_putw_at(s, 0, stream_get_endp(s));
(void)zclient_send_message(zclient);
-
}
/* Link State registration */
return 0;
}
+int sharp_zebra_send_tc_filter_rate(struct interface *ifp,
+ const struct prefix *source,
+ const struct prefix *destination,
+ uint8_t ip_proto, uint16_t src_port,
+ uint16_t dst_port, uint64_t rate)
+{
+#define SHARPD_TC_HANDLE 0x0001
+ struct stream *s;
+
+ s = zclient->obuf;
+
+ struct tc_qdisc q = {.ifindex = ifp->ifindex, .kind = TC_QDISC_HTB};
+
+ zapi_tc_qdisc_encode(ZEBRA_TC_QDISC_INSTALL, s, &q);
+ if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
+ return -1;
+
+ struct tc_class c = {.ifindex = ifp->ifindex,
+ .handle = SHARPD_TC_HANDLE & 0xffff,
+ .kind = TC_QDISC_HTB,
+ .u.htb.ceil = rate,
+ .u.htb.rate = rate};
+
+ zapi_tc_class_encode(ZEBRA_TC_CLASS_ADD, s, &c);
+ if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
+ return -1;
+
+ struct tc_filter f = {.ifindex = ifp->ifindex,
+ .handle = SHARPD_TC_HANDLE,
+ .priority = 0x1,
+ .kind = TC_FILTER_FLOWER,
+ .u.flower.filter_bm = 0};
+
+#ifdef ETH_P_IP
+ f.protocol = ETH_P_IP;
+#else
+ f.protocol = 0x0800;
+#endif
+
+ f.u.flower.filter_bm |= TC_FLOWER_IP_PROTOCOL;
+ f.u.flower.ip_proto = ip_proto;
+ f.u.flower.filter_bm |= TC_FLOWER_SRC_IP;
+ prefix_copy(&f.u.flower.src_ip, source);
+ f.u.flower.filter_bm |= TC_FLOWER_DST_IP;
+ prefix_copy(&f.u.flower.dst_ip, destination);
+ f.u.flower.filter_bm |= TC_FLOWER_SRC_PORT;
+ f.u.flower.src_port_min = f.u.flower.src_port_max = src_port;
+ f.u.flower.filter_bm |= TC_FLOWER_DST_PORT;
+ f.u.flower.dst_port_min = f.u.flower.dst_port_max = dst_port;
+ f.u.flower.classid = SHARPD_TC_HANDLE & 0xffff;
+
+ zapi_tc_filter_encode(ZEBRA_TC_FILTER_ADD, s, &f);
+ if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
+ return -1;
+
+ return 0;
+}
+
static zclient_handler *const sharp_handlers[] = {
[ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
{
struct zclient_options opt = {.receive_notify = true};
- if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up,
- sharp_ifp_down, sharp_ifp_destroy);
+ if_zapi_callbacks(sharp_ifp_create, sharp_ifp_up, sharp_ifp_down,
+ sharp_ifp_destroy);
zclient = zclient_new(master, &opt, sharp_handlers,
array_size(sharp_handlers));