@@ -438,6 +438,56 @@
return err != 0;
}
+static int br_cmd_mirror(int argc, char *const* argv)
+{
+ int mirror_state = 0, err;
+ const char *brname = *++argv;
+ const char *ifname = *++argv;
+ const char *ifmode = *++argv;
+
+ if (!strcmp(ifmode, "dst") || !strcmp(ifmode, "destination")
+ || !strcmp(ifmode, "4"))
+ mirror_state |= BR_MIRROR_DST ;
+
+ else if (!strcmp(ifmode, "both") || !strcmp(ifmode, "all")
+ || !strcmp(ifmode, "3"))
+ mirror_state |= (BR_MIRROR_RX | BR_MIRROR_TX);
+
+ else if (!strcmp(ifmode, "tx") || !strcmp(ifmode, "egress")
+ || !strcmp(ifmode, "2"))
+ mirror_state |= BR_MIRROR_TX;
+
+ else if (!strcmp(ifmode, "rx") || !strcmp(ifmode, "ingress")
+ || !strcmp(ifmode, "1"))
+ mirror_state |= BR_MIRROR_RX;
+
+ else if (!strcmp(ifmode, "off") || !strcmp(ifmode, "no")
+ || !strcmp(ifmode, "0"))
+ mirror_state &= BR_MIRROR_OFF;
+
+ else {
+ fprintf(stderr, "expect rx/tx/both/off/dst for argument\n");
+ return 1;
+ }
+ if (if_nametoindex(ifname) == 0) {
+ fprintf(stderr, "interface %s does not exist!\n",
+ ifname);
+ return 1;
+ } else if (if_nametoindex(brname) == 0) {
+ fprintf(stderr, "bridge %s does not exist!\n",
+ brname);
+ return 1;
+ }
+
+ err = br_set_mirror_state(brname, ifname, mirror_state);
+
+ if (err) {
+ fprintf(stderr, "can't set %s to %s state on bridge %s: %s\n",
+ ifname,ifmode,brname, strerror(err));
+ }
+ return err != 0;
+}
+
static const struct command commands[] = {
{ 1, "addbr", br_cmd_addbr, "<bridge>\t\tadd bridge" },
{ 1, "delbr", br_cmd_delbr, "<bridge>\t\tdelete bridge" },
@@ -469,6 +519,8 @@
"<bridge>\t\tshow bridge stp info"},
{ 2, "stp", br_cmd_stp,
"<bridge> {on|off}\tturn stp on/off" },
+ { 3, "mirror", br_cmd_mirror,
+ "<bridge> <interface> {rx|tx|both|off|dst}\tset interface mirroring state" },
};
const struct command *command_lookup(const char *cmd)
@@ -272,6 +272,7 @@
fetch_tv(path, "forward_delay_timer", &info->forward_delay_timer_value);
fetch_tv(path, "hold_timer", &info->hold_timer_value);
info->hairpin_mode = fetch_int(path, "hairpin_mode");
+ info->mirror_state = fetch_int(path, "mirror_state");
closedir(d);
@@ -388,6 +389,11 @@
return port_set(bridge, port, "hairpin_mode", hairpin_mode, 0);
}
+int br_set_mirror_state(const char *bridge, const char *port, int mirror_state)
+{
+ return port_set(bridge, port, "mirror_state", mirror_state, 0);
+}
+
static inline void __copy_fdb(struct fdb_entry *ent,
const struct __fdb_entry *f)
{
@@ -82,8 +82,14 @@
struct timeval forward_delay_timer_value;
struct timeval hold_timer_value;
unsigned char hairpin_mode;
+ unsigned char mirror_state;
};
+#define BR_MIRROR_OFF 0x00
+#define BR_MIRROR_RX 0x01
+#define BR_MIRROR_TX 0x02
+#define BR_MIRROR_DST 0x04
+
extern int br_init(void);
extern int br_refresh(void);
extern void br_shutdown(void);
@@ -117,4 +123,6 @@
unsigned long skip, int num);
extern int br_set_hairpin_mode(const char *bridge, const char *dev,
int hairpin_mode);
+extern int br_set_mirror_state(const char *brname, const char *dev,
+ int mirror_state);
#endif