*/
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <net/if.h>
}
static void
-iface_config_set(struct qosify_iface_config *cfg, struct blob_attr *attr)
+iface_config_set(struct qosify_iface *iface, struct blob_attr *attr)
{
+ struct qosify_iface_config *cfg = &iface->config;
struct blob_attr *tb[__IFACE_ATTR_MAX];
struct blob_attr *cur;
cfg->ingress = true;
cfg->egress = true;
cfg->host_isolate = true;
- cfg->autorate_ingress = true;
+ cfg->autorate_ingress = false;
+ cfg->nat = !iface->device;
if ((cur = tb[IFACE_ATTR_BW_UP]) != NULL)
cfg->bandwidth_up = check_str(cur);
return ifname;
}
-static int run_cmd(char *cmd, bool ignore)
-{
- char *argv[] = { "sh", "-c", cmd, NULL };
- bool first = true;
- int status = -1;
- char buf[512];
- int fds[2];
- FILE *f;
- int pid;
-
- if (pipe(fds))
- return -1;
-
- pid = fork();
- if (!pid) {
- close(fds[0]);
- if (fds[1] != STDOUT_FILENO)
- dup2(fds[1], STDOUT_FILENO);
- if (fds[1] != STDERR_FILENO)
- dup2(fds[1], STDERR_FILENO);
- if (fds[1] > STDERR_FILENO)
- close(fds[1]);
- execv("/bin/sh", argv);
- exit(1);
- }
-
- if (pid < 0)
- return -1;
-
- close(fds[1]);
- f = fdopen(fds[0], "r");
- if (!f) {
- close(fds[0]);
- goto out;
- }
-
- while (fgets(buf, sizeof(buf), f) != NULL) {
- if (!strlen(buf))
- break;
- if (ignore)
- continue;
- if (first) {
- ULOG_WARN("Command: %s\n", cmd);
- first = false;
- }
- ULOG_WARN("%s%s", buf, strchr(buf, '\n') ? "" : "\n");
- }
-
- fclose(f);
-
-out:
- while (waitpid(pid, &status, 0) < 0)
- if (errno != EINTR)
- break;
-
- return status;
-}
-
static int
prepare_tc_cmd(char *buf, int len, const char *type, const char *cmd,
const char *dev, const char *extra)
prepare_tc_cmd(buf, sizeof(buf), "qdisc", "del", ifname, type);
- return run_cmd(buf, true);
+ return qosify_run_cmd(buf, true);
}
static int
APPEND(buf, ofs, " bandwidth %s", bw);
APPEND(buf, ofs, " %s %sgress", cfg->mode, egress ? "e" : "in");
+ if (!egress && cfg->autorate_ingress)
+ APPEND(buf, ofs, " autorate-ingress");
if (cfg->host_isolate)
APPEND(buf, ofs, " %snat dual-%shost",
cfg->common_opts ? cfg->common_opts : "",
dir_opts ? dir_opts : "");
- run_cmd(buf, false);
+ qosify_run_cmd(buf, false);
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", ifname, "parent 1: bpf");
APPEND(buf, ofs, " object-pinned /sys/fs/bpf/qosify_%sgress_%s verbose direct-action",
egress ? "e" : "in",
eth ? "eth" : "ip");
- return run_cmd(buf, false);
+ return qosify_run_cmd(buf, false);
}
static int
cmd_del_qdisc(iface->ifname, "handle ffff: ingress");
snprintf(buf, sizeof(buf), "ip link del '%s'", interface_ifb_name(iface));
- return run_cmd(buf, true);
+ return qosify_run_cmd(buf, true);
}
cmd_del_ingress(iface);
ofs = prepare_tc_cmd(buf, sizeof(buf), "qdisc", "add", iface->ifname, " handle ffff: ingress");
- run_cmd(buf, false);
+ qosify_run_cmd(buf, false);
+
+ ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
+ APPEND(buf, ofs, " protocol ip prio 5 u32 match ip sport 53 0xffff "
+ "flowid 1:1 action mirred egress redirect dev ifb-dns");
+ qosify_run_cmd(buf, false);
+
+ ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
+ APPEND(buf, ofs, " protocol ip prio 5 u32 match ip sport 53 0xffff "
+ "flowid 1:1 action mirred egress redirect dev ifb-dns");
+ qosify_run_cmd(buf, false);
+
+ ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
+ APPEND(buf, ofs, " protocol 802.1Q prio 6 u32 offset plus 4 match ip sport 53 0xffff "
+ "flowid 1:1 action mirred egress redirect dev ifb-dns");
+ qosify_run_cmd(buf, false);
+
+ ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
+ APPEND(buf, ofs, " protocol ipv6 prio 7 u32 match ip6 sport 53 0xffff "
+ "flowid 1:1 action mirred egress redirect dev ifb-dns");
+ qosify_run_cmd(buf, false);
+
+ ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
+ APPEND(buf, ofs, " protocol ipv6 prio 8 u32 offset plus 4 match ip6 sport 53 0xffff "
+ "flowid 1:1 action mirred egress redirect dev ifb-dns");
+ qosify_run_cmd(buf, false);
+
+ if (!iface->config.ingress)
+ return 0;
snprintf(buf, sizeof(buf), "ip link add '%s' type ifb", ifbdev);
- run_cmd(buf, false);
+ qosify_run_cmd(buf, false);
cmd_add_qdisc(iface, ifbdev, false, eth);
snprintf(buf, sizeof(buf), "ip link set dev '%s' up", ifbdev);
- run_cmd(buf, false);
+ qosify_run_cmd(buf, false);
ofs = prepare_tc_cmd(buf, sizeof(buf), "filter", "add", iface->ifname, " parent ffff:");
APPEND(buf, ofs, " protocol all prio 10 u32 match u32 0 0 "
"flowid 1:1 action mirred egress redirect dev '%s'", ifbdev);
- return run_cmd(buf, false);
+ return qosify_run_cmd(buf, false);
}
static void
if (iface->config.egress)
cmd_add_qdisc(iface, iface->ifname, true, eth);
- if (iface->config.ingress)
- cmd_add_ingress(iface, eth);
+ cmd_add_ingress(iface, eth);
iface->active = true;
}
interface_set_config(struct qosify_iface *iface, struct blob_attr *config)
{
iface->config_data = blob_memdup(config);
- iface_config_set(&iface->config, iface->config_data);
+ iface_config_set(iface, iface->config_data);
interface_start(iface);
}
uloop_timeout_set(&timer, 10);
}
+static void
+__qosify_iface_status(struct blob_buf *b, struct qosify_iface *iface)
+{
+ void *c;
+
+ c = blobmsg_open_table(b, qosify_iface_name(iface));
+ blobmsg_add_u8(b, "active", iface->active);
+ if (iface->ifname)
+ blobmsg_add_string(b, "ifname", iface->ifname);
+ blobmsg_add_u8(b, "egress", iface->config.egress);
+ blobmsg_add_u8(b, "ingress", iface->config.ingress);
+ blobmsg_close_table(b, c);
+
+}
+
void qosify_iface_status(struct blob_buf *b)
{
struct qosify_iface *iface;
- void *c, *i;
+ void *c;
c = blobmsg_open_table(b, "devices");
- vlist_for_each_element(&devices, iface, node) {
- i = blobmsg_open_table(b, qosify_iface_name(iface));
- blobmsg_add_u8(b, "active", iface->active);
- blobmsg_close_table(b, i);
- }
+ vlist_for_each_element(&devices, iface, node)
+ __qosify_iface_status(b, iface);
blobmsg_close_table(b, c);
c = blobmsg_open_table(b, "interfaces");
- vlist_for_each_element(&interfaces, iface, node) {
- i = blobmsg_open_table(b, qosify_iface_name(iface));
- blobmsg_add_u8(b, "active", iface->active);
- if (iface->ifname)
- blobmsg_add_string(b, "ifname", iface->ifname);
- blobmsg_close_table(b, i);
- }
+ vlist_for_each_element(&interfaces, iface, node)
+ __qosify_iface_status(b, iface);
blobmsg_close_table(b, c);
}