"BOOL := [1|0]\n"
"FEATURES := ecn\n"
"ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl ]\n"
- "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n"
+ "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL ]\n"
"SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n"
"SEGMODE := [ encap | inline ]\n"
+ "SEG6LOCAL := action ACTION [ OPTIONS ] [ count ]\n"
+ "ACTION := { End | End.X | End.T | End.DX2 | End.DX6 | End.DX4 |\n"
+ " End.DT6 | End.DT4 | End.B6 | End.B6.Encaps | End.BM |\n"
+ " End.S | End.AS | End.AM | End.BPF }\n"
+ "OPTIONS := OPTION [ OPTIONS ]\n"
+ "OPTION := { srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |\n"
+ " table TABLEID | vrftable TABLEID | endpoint PROGNAME }\n"
"ROUTE_GET_FLAGS := [ fibmatch ]\n");
exit(-1);
}
}
}
+static void print_seg6_local_counters(FILE *fp, struct rtattr *encap)
+{
+ struct rtattr *tb[SEG6_LOCAL_CNT_MAX + 1];
+ __u64 packets = 0, bytes = 0, errors = 0;
+
+ parse_rtattr_nested(tb, SEG6_LOCAL_CNT_MAX, encap);
+
+ if (tb[SEG6_LOCAL_CNT_PACKETS])
+ packets = rta_getattr_u64(tb[SEG6_LOCAL_CNT_PACKETS]);
+
+ if (tb[SEG6_LOCAL_CNT_BYTES])
+ bytes = rta_getattr_u64(tb[SEG6_LOCAL_CNT_BYTES]);
+
+ if (tb[SEG6_LOCAL_CNT_ERRORS])
+ errors = rta_getattr_u64(tb[SEG6_LOCAL_CNT_ERRORS]);
+
+ if (is_json_context()) {
+ open_json_object("stats64");
+
+ print_u64(PRINT_JSON, "packets", NULL, packets);
+ print_u64(PRINT_JSON, "bytes", NULL, bytes);
+ print_u64(PRINT_JSON, "errors", NULL, errors);
+
+ close_json_object();
+ } else {
+ print_string(PRINT_FP, NULL, "%s ", "packets");
+ print_num(fp, 1, packets);
+
+ print_string(PRINT_FP, NULL, "%s ", "bytes");
+ print_num(fp, 1, bytes);
+
+ print_string(PRINT_FP, NULL, "%s ", "errors");
+ print_num(fp, 1, errors);
+ }
+}
+
static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[SEG6_LOCAL_MAX + 1];
if (tb[SEG6_LOCAL_BPF])
print_encap_bpf_prog(fp, tb[SEG6_LOCAL_BPF], "endpoint");
+
+ if (tb[SEG6_LOCAL_COUNTERS] && show_stats)
+ print_seg6_local_counters(fp, tb[SEG6_LOCAL_COUNTERS]);
}
static void print_encap_mpls(FILE *fp, struct rtattr *encap)
return 0;
}
+/* for the moment, counters are always initialized to zero by the kernel; so we
+ * do not expect to parse any argument here.
+ */
+static int seg6local_fill_counters(struct rtattr *rta, size_t len, int attr)
+{
+ struct rtattr *nest;
+ int ret;
+
+ nest = rta_nest(rta, len, attr);
+
+ ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_PACKETS, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_BYTES, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_ERRORS, 0);
+ if (ret < 0)
+ return ret;
+
+ rta_nest_end(rta, nest);
+ return 0;
+}
+
static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
char ***argvp)
{
int segs_ok = 0, hmac_ok = 0, table_ok = 0, vrftable_ok = 0;
+ int action_ok = 0, srh_ok = 0, bpf_ok = 0, counters_ok = 0;
int nh4_ok = 0, nh6_ok = 0, iif_ok = 0, oif_ok = 0;
__u32 action = 0, table, vrftable, iif, oif;
- int action_ok = 0, srh_ok = 0, bpf_ok = 0;
struct ipv6_sr_hdr *srh;
char **argv = *argvp;
int argc = *argcp;
if (!oif)
exit(nodev(*argv));
ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
+ } else if (strcmp(*argv, "count") == 0) {
+ if (counters_ok++)
+ duparg2("count", *argv);
+ ret = seg6local_fill_counters(rta, len,
+ SEG6_LOCAL_COUNTERS);
} else if (strcmp(*argv, "srh") == 0) {
NEXT_ARG();
if (srh_ok++)
.B seg6local
.BR action
.IR SEG6_ACTION " [ "
-.IR SEG6_ACTION_PARAM " ] "
+.IR SEG6_ACTION_PARAM " ] [ "
+.BR count " ] "
.ti -8
.IR ROUTE_GET_FLAGS " := "
.B seg6local
.in +2
.IR SEG6_ACTION " [ "
-.IR SEG6_ACTION_PARAM " ] "
-- Operation to perform on matching packets.
+.IR SEG6_ACTION_PARAM " ] [ "
+.BR count " ] "
+- Operation to perform on matching packets. The optional \fBcount\fR
+attribute is used to collect statistics on the processing of actions.
+Three counters are implemented: 1) packets correctly processed;
+2) bytes correctly processed; 3) packets that cause a processing error
+(i.e., missing SID List, wrong SID List, etc). To retrieve the counters
+related to an action use the \fB-s\fR flag in the \fBshow\fR command.
The following actions are currently supported (\fBLinux 4.14+ only\fR).
.in +2