cangw: support new can-gw features for Linux 3.9+

Added new option '-i' for can-gw rules to allow to route CAN frames back to the
originating/incoming CAN interface (which is disabled by default).

CAN frames that are deleted due to the violation of the max_hops limit are now
printed when displaying the configured rules with 'cangw -L'.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
pull/7/head
Oliver Hartkopp 2013-01-29 20:17:52 +01:00
parent 221794dbe8
commit 9dad9f7354
2 changed files with 21 additions and 3 deletions

22
cangw.c
View File

@ -192,6 +192,7 @@ void print_usage(char *prg)
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n"); fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
fprintf(stderr, "Options: -t (preserve src_dev rx timestamp)\n"); fprintf(stderr, "Options: -t (preserve src_dev rx timestamp)\n");
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n"); fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
fprintf(stderr, " -i (allow to route to incoming interface)\n");
fprintf(stderr, " -f <filter> (set CAN filter)\n"); fprintf(stderr, " -f <filter> (set CAN filter)\n");
fprintf(stderr, " -m <mod> (set frame modifications)\n"); fprintf(stderr, " -m <mod> (set frame modifications)\n");
fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n"); fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n");
@ -353,7 +354,7 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
unsigned int src_ifindex = 0; unsigned int src_ifindex = 0;
unsigned int dst_ifindex = 0; unsigned int dst_ifindex = 0;
__u32 handled, dropped; __u32 handled, dropped, deleted;
int rtlen; int rtlen;
@ -394,6 +395,7 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
handled = 0; handled = 0;
dropped = 0; dropped = 0;
deleted = 0;
src_ifindex = 0; src_ifindex = 0;
dst_ifindex = 0; dst_ifindex = 0;
@ -432,6 +434,10 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
dropped = *(__u32 *)RTA_DATA(rta); dropped = *(__u32 *)RTA_DATA(rta);
break; break;
case CGW_DELETED:
deleted = *(__u32 *)RTA_DATA(rta);
break;
default: default:
printf("Unknown attribute %d!", rta->rta_type); printf("Unknown attribute %d!", rta->rta_type);
return -EINVAL; return -EINVAL;
@ -449,6 +455,9 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
if (rtc->flags & CGW_FLAGS_CAN_SRC_TSTAMP) if (rtc->flags & CGW_FLAGS_CAN_SRC_TSTAMP)
printf("-t "); printf("-t ");
if (rtc->flags & CGW_FLAGS_CAN_IIF_TX_OK)
printf("-i ");
/* second parse for mod attributes */ /* second parse for mod attributes */
rta = (struct rtattr *) RTCAN_RTA(rtc); rta = (struct rtattr *) RTCAN_RTA(rtc);
rtlen = RTCAN_PAYLOAD(nlh); rtlen = RTCAN_PAYLOAD(nlh);
@ -489,6 +498,7 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
case CGW_DST_IF: case CGW_DST_IF:
case CGW_HANDLED: case CGW_HANDLED:
case CGW_DROPPED: case CGW_DROPPED:
case CGW_DELETED:
break; break;
default: default:
@ -498,7 +508,9 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
} }
} }
printf("# %d handled %d dropped\n", handled, dropped); /* end of entry */ /* end of entry */
printf("# %d handled %d dropped %d deleted\n",
handled, dropped, deleted);
/* jump to next NLMSG in the given buffer */ /* jump to next NLMSG in the given buffer */
nlh = NLMSG_NEXT(nlh, len); nlh = NLMSG_NEXT(nlh, len);
@ -548,7 +560,7 @@ int main(int argc, char **argv)
memset(&cs_xor, 0, sizeof(cs_xor)); memset(&cs_xor, 0, sizeof(cs_xor));
memset(&cs_crc8, 0, sizeof(cs_crc8)); memset(&cs_crc8, 0, sizeof(cs_crc8));
while ((opt = getopt(argc, argv, "ADFLs:d:tef:c:p:x:m:?")) != -1) { while ((opt = getopt(argc, argv, "ADFLs:d:teif:c:p:x:m:?")) != -1) {
switch (opt) { switch (opt) {
case 'A': case 'A':
@ -587,6 +599,10 @@ int main(int argc, char **argv)
flags |= CGW_FLAGS_CAN_ECHO; flags |= CGW_FLAGS_CAN_ECHO;
break; break;
case 'i':
flags |= CGW_FLAGS_CAN_IIF_TX_OK;
break;
case 'f': case 'f':
if (sscanf(optarg, "%x:%x", &filter.can_id, if (sscanf(optarg, "%x:%x", &filter.can_id,
&filter.can_mask) == 2) { &filter.can_mask) == 2) {

View File

@ -44,6 +44,7 @@ enum {
CGW_SRC_IF, /* ifindex of source network interface */ CGW_SRC_IF, /* ifindex of source network interface */
CGW_DST_IF, /* ifindex of destination network interface */ CGW_DST_IF, /* ifindex of destination network interface */
CGW_FILTER, /* specify struct can_filter on source CAN device */ CGW_FILTER, /* specify struct can_filter on source CAN device */
CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */
__CGW_MAX __CGW_MAX
}; };
@ -51,6 +52,7 @@ enum {
#define CGW_FLAGS_CAN_ECHO 0x01 #define CGW_FLAGS_CAN_ECHO 0x01
#define CGW_FLAGS_CAN_SRC_TSTAMP 0x02 #define CGW_FLAGS_CAN_SRC_TSTAMP 0x02
#define CGW_FLAGS_CAN_IIF_TX_OK 0x04
#define CGW_MOD_FUNCS 4 /* AND OR XOR SET */ #define CGW_MOD_FUNCS 4 /* AND OR XOR SET */