#include <string.h>
#include <linux/if.h>
#include <limits.h>
-
+#include <inttypes.h>
#include "utils.h"
#include "tc_util.h"
+#ifdef CONFIG_HAVE_LINUX_CAN_H
+ #include "linux/can.h"
+
+#elif !defined(CAN_EFF_FLAG)
+ /* special address description flags for the CAN_ID */
+ #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
+ #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
+ #define CAN_ERR_FLAG 0x20000000U /* error frame */
+
+ /* valid bits in CAN ID for frame formats */
+ #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
+ #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
+ #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
+#endif
+
+
struct canprio_rule {
__u32 canid;
__u32 canid_mask;
};
-
struct canprio_rule canprio_rules[32];
static void explain(void)
{
- fprintf(stderr, "Usage: ... canprio match CANID:MASK flowid FLOWID\n");
+ fprintf(stderr, "Usage: ... canprio [ MATCHSPEC ] [ flowid FLOWID ]\n"
+ "\n"
+ "Where: MATCHSPEC := { matchid FILTERID | matcheid FILTERID | \n"
+ " MATCHSPEC ... }\n"
+ " FILTERID := CANID:MASK \n"
+ "\n"
+ "NOTE: CLASSID, CANID, MASK is parsed as hexadecimal input.\n");
}
struct tcmsg *t = NLMSG_DATA(n); // Why?
struct rtattr *tail;
long h = 0;
- __u32 canid, canid_mask;
+ __u32 canid;
+ __u32 canid_mask;
int rules_count = 0;
if (argc == 0)
//printf(" [parsing match ...");
NEXT_ARG();
- //FIXME why it does not work with "%jx"?
- if (sscanf(*argv, "%lx:%lx", &canid, &canid_mask) != 2) {
+ if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
return -1;
}
//printf("... 0x%x:0x%x]\n", canid, canid_mask);
- if (canid > 0) {// FIXME boundary check
+ if (canid >= 0) {// FIXME boundary check
canprio_rules[rules_count].canid = canid;
canprio_rules[rules_count].canid_mask = canid_mask;
rules_count++;
+
+ }
+
+ } else if (matches(*argv, "matchid") == 0) {
+ NEXT_ARG();
+
+ if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
+ fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
+ return -1;
+ }
+
+ if (canid & ~CAN_SFF_MASK) {
+ fprintf(stderr, "Id 0x%lx exceeded standard CAN ID range.",
+ (unsigned long)canid);
+ return -1;
+ }
+
+ canprio_rules[rules_count].canid = canid;
+ canprio_rules[rules_count].canid_mask = (canid_mask & CAN_SFF_MASK);
+ rules_count++;
+
+ } else if (matches(*argv, "matcheid") == 0) {
+ NEXT_ARG();
+
+ if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
+ fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
+ return -1;
+ }
+
+ if (canid & ~CAN_EFF_MASK) {
+ fprintf(stderr, "Id 0x%lx exceeded extended CAN ID range.",
+ (unsigned long)canid);
+ return -1;
}
+ canprio_rules[rules_count].canid = canid | CAN_EFF_FLAG;
+ canprio_rules[rules_count].canid_mask = (canid_mask & CAN_EFF_MASK);
+ rules_count++;
+
} else if (matches(*argv, "classid") == 0 ||
strcmp(*argv, "flowid") == 0) {
//printf(" [parsing flowid]\n");