cherry-pick.softflowd-0.9.9-6-g9478639.this-commit-includes-2-changes.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. Subject: This commit includes 2 changes
  2. Origin: softflowd-0.9.9-6-g9478639 <https://github.com/irino/softflowd/commit/softflowd-0.9.9-6-g9478639>
  3. Upstream-Author: Hitoshi Irino <hitoshi.irino@gmail.com>
  4. Date: Mon Mar 17 13:10:54 2014 +0900
  5. 1. It enables metering and exporting vlanid when using NetFlow v9 and IPFIX.
  6. 2. When ICMP flow information are exported It uses the ICMP_TYPE field instead of the L4_DST_PORT field
  7. --- a/configure.ac
  8. +++ b/configure.ac
  9. @@ -31,6 +31,11 @@
  10. [ --enable-gcc-warnings Enable verbose warnings (only for gcc)],
  11. [ if test "x$enableval" = "xyes" ; then CFLAGS="$CFLAGS $WFLAGS"; fi ]
  12. )
  13. +AC_ARG_ENABLE(nf9-vlan,
  14. + AC_HELP_STRING([--enable-nf9-vlan],
  15. + [enable exporting VLAN (and ICMP_TYPE) field in NetFlow v9 (default is NO)]),
  16. + AC_DEFINE([ENABLE_NF9_VLAN], 1, [enable exporting VLAN (and ICMP_TYPE) field in NetFlow v9]))
  17. +
  18. AC_ARG_WITH(cflags,
  19. [ --with-cflags Specify additional compiler flags],
  20. [ if test "x$withval" != "xno" ; then CFLAGS="$CFLAGS $withval"; fi ]
  21. --- a/ipfix.c
  22. +++ b/ipfix.c
  23. @@ -85,8 +85,15 @@
  24. #define IPFIX_sourceIPv6Address 27
  25. #define IPFIX_destinationIPv6Address 28
  26. /* ... */
  27. +#define IPFIX_icmpTypeCodeIPv4 32
  28. +/* ... */
  29. +/* ... */
  30. +#define IPFIX_vlanId 58
  31. +
  32. #define IPFIX_ipVersion 60
  33. /* ... */
  34. +#define IPFIX_icmpTypeCodeIPv6 139
  35. +/* ... */
  36. #define IPFIX_meteringProcessId 143
  37. /* ... */
  38. #define IPFIX_flowStartSeconds 150
  39. @@ -107,7 +114,7 @@
  40. #define PSAMP_selectorAlgorithm_count 1
  41. /* Stuff pertaining to the templates that softflowd uses */
  42. -#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 14
  43. +#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 16
  44. struct IPFIX_SOFTFLOWD_TEMPLATE {
  45. struct IPFIX_TEMPLATE_SET_HEADER h;
  46. struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS];
  47. @@ -127,6 +134,7 @@
  48. u_int32_t ingressInterface, egressInterface;
  49. u_int16_t sourceTransportPort, destinationTransportPort;
  50. u_int8_t protocolIdentifier, tcpControlBits, ipVersion, ipClassOfService;
  51. + u_int16_t icmpTypeCode, vlanId;
  52. //u_int32_t flowEndSysUpTime, flowStartSysUpTime;
  53. } __packed;
  54. @@ -220,31 +228,35 @@
  55. v4_template.r[10].length = htons(1);
  56. v4_template.r[11].ie = htons(IPFIX_ipClassOfService);
  57. v4_template.r[11].length = htons(1);
  58. + v4_template.r[12].ie = htons(IPFIX_icmpTypeCodeIPv4);
  59. + v4_template.r[12].length = htons(2);
  60. + v4_template.r[13].ie = htons(IPFIX_vlanId);
  61. + v4_template.r[13].length = htons(2);
  62. if (param->time_format == 's') {
  63. - v4_template.r[12].ie = htons(IPFIX_flowStartSeconds);
  64. - v4_template.r[12].length = htons(sizeof(u_int32_t));
  65. - v4_template.r[13].ie = htons(IPFIX_flowEndSeconds);
  66. - v4_template.r[13].length = htons(sizeof(u_int32_t));
  67. + v4_template.r[14].ie = htons(IPFIX_flowStartSeconds);
  68. + v4_template.r[14].length = htons(sizeof(u_int32_t));
  69. + v4_template.r[15].ie = htons(IPFIX_flowEndSeconds);
  70. + v4_template.r[15].length = htons(sizeof(u_int32_t));
  71. } else if (param->time_format == 'm') {
  72. - v4_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
  73. - v4_template.r[12].length = htons(sizeof(u_int64_t));
  74. - v4_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
  75. - v4_template.r[13].length = htons(sizeof(u_int64_t));
  76. + v4_template.r[14].ie = htons(IPFIX_flowStartMilliSeconds);
  77. + v4_template.r[14].length = htons(sizeof(u_int64_t));
  78. + v4_template.r[15].ie = htons(IPFIX_flowEndMilliSeconds);
  79. + v4_template.r[15].length = htons(sizeof(u_int64_t));
  80. } else if (param->time_format == 'M') {
  81. - v4_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
  82. - v4_template.r[12].length = htons(sizeof(u_int64_t));
  83. - v4_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
  84. - v4_template.r[13].length = htons(sizeof(u_int64_t));
  85. + v4_template.r[14].ie = htons(IPFIX_flowStartMicroSeconds);
  86. + v4_template.r[14].length = htons(sizeof(u_int64_t));
  87. + v4_template.r[15].ie = htons(IPFIX_flowEndMicroSeconds);
  88. + v4_template.r[15].length = htons(sizeof(u_int64_t));
  89. } else if (param->time_format == 'n') {
  90. - v4_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
  91. - v4_template.r[12].length = htons(sizeof(u_int64_t));
  92. - v4_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
  93. - v4_template.r[13].length = htons(sizeof(u_int64_t));
  94. + v4_template.r[14].ie = htons(IPFIX_flowStartNanoSeconds);
  95. + v4_template.r[14].length = htons(sizeof(u_int64_t));
  96. + v4_template.r[15].ie = htons(IPFIX_flowEndNanoSeconds);
  97. + v4_template.r[15].length = htons(sizeof(u_int64_t));
  98. } else {
  99. - v4_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
  100. - v4_template.r[12].length = htons(sizeof(u_int32_t));
  101. - v4_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
  102. - v4_template.r[13].length = htons(sizeof(u_int32_t));
  103. + v4_template.r[14].ie = htons(IPFIX_flowStartSysUpTime);
  104. + v4_template.r[14].length = htons(sizeof(u_int32_t));
  105. + v4_template.r[15].ie = htons(IPFIX_flowEndSysUpTime);
  106. + v4_template.r[15].length = htons(sizeof(u_int32_t));
  107. }
  108. bzero(&v6_template, sizeof(v6_template));
  109. @@ -276,31 +288,35 @@
  110. v6_template.r[10].length = htons(1);
  111. v6_template.r[11].ie = htons(IPFIX_ipClassOfService);
  112. v6_template.r[11].length = htons(1);
  113. + v6_template.r[12].ie = htons(IPFIX_icmpTypeCodeIPv6);
  114. + v6_template.r[12].length = htons(2);
  115. + v6_template.r[13].ie = htons(IPFIX_vlanId);
  116. + v6_template.r[13].length = htons(2);
  117. if (param->time_format == 's') {
  118. - v6_template.r[12].ie = htons(IPFIX_flowStartSeconds);
  119. - v6_template.r[12].length = htons(sizeof(u_int32_t));
  120. - v6_template.r[13].ie = htons(IPFIX_flowEndSeconds);
  121. - v6_template.r[13].length = htons(sizeof(u_int32_t));
  122. + v6_template.r[14].ie = htons(IPFIX_flowStartSeconds);
  123. + v6_template.r[14].length = htons(sizeof(u_int32_t));
  124. + v6_template.r[15].ie = htons(IPFIX_flowEndSeconds);
  125. + v6_template.r[15].length = htons(sizeof(u_int32_t));
  126. } else if (param->time_format == 'm') {
  127. - v6_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
  128. - v6_template.r[12].length = htons(sizeof(u_int64_t));
  129. - v6_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
  130. - v6_template.r[13].length = htons(sizeof(u_int64_t));
  131. + v6_template.r[14].ie = htons(IPFIX_flowStartMilliSeconds);
  132. + v6_template.r[14].length = htons(sizeof(u_int64_t));
  133. + v6_template.r[15].ie = htons(IPFIX_flowEndMilliSeconds);
  134. + v6_template.r[15].length = htons(sizeof(u_int64_t));
  135. } else if (param->time_format == 'M') {
  136. - v6_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
  137. - v6_template.r[12].length = htons(sizeof(u_int64_t));
  138. - v6_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
  139. - v6_template.r[13].length = htons(sizeof(u_int64_t));
  140. + v6_template.r[14].ie = htons(IPFIX_flowStartMicroSeconds);
  141. + v6_template.r[14].length = htons(sizeof(u_int64_t));
  142. + v6_template.r[15].ie = htons(IPFIX_flowEndMicroSeconds);
  143. + v6_template.r[15].length = htons(sizeof(u_int64_t));
  144. } else if (param->time_format == 'n') {
  145. - v6_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
  146. - v6_template.r[12].length = htons(sizeof(u_int64_t));
  147. - v6_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
  148. - v6_template.r[13].length = htons(sizeof(u_int64_t));
  149. + v6_template.r[14].ie = htons(IPFIX_flowStartNanoSeconds);
  150. + v6_template.r[14].length = htons(sizeof(u_int64_t));
  151. + v6_template.r[15].ie = htons(IPFIX_flowEndNanoSeconds);
  152. + v6_template.r[15].length = htons(sizeof(u_int64_t));
  153. } else {
  154. - v6_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
  155. - v6_template.r[12].length = htons(sizeof(u_int32_t));
  156. - v6_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
  157. - v6_template.r[13].length = htons(sizeof(u_int32_t));
  158. + v6_template.r[14].ie = htons(IPFIX_flowStartSysUpTime);
  159. + v6_template.r[14].length = htons(sizeof(u_int32_t));
  160. + v6_template.r[15].ie = htons(IPFIX_flowEndSysUpTime);
  161. + v6_template.r[15].length = htons(sizeof(u_int32_t));
  162. }
  163. }
  164. @@ -427,6 +443,11 @@
  165. dc[1]->tcpControlBits = flow->tcp_flags[1];
  166. dc[0]->ipClassOfService = flow->tos[0];
  167. dc[1]->ipClassOfService = flow->tos[1];
  168. + if (flow->protocol == IPPROTO_ICMP || flow->protocol == IPPROTO_ICMPV6) {
  169. + dc[0]->icmpTypeCode = dc[0]->destinationTransportPort;
  170. + dc[1]->icmpTypeCode = dc[1]->destinationTransportPort;
  171. + }
  172. + dc[0]->vlanId = dc[1]->vlanId = htons(flow->vlanid);
  173. if (flow->octets[0] > 0) {
  174. if (ret_len + freclen > len)
  175. --- a/netflow9.c
  176. +++ b/netflow9.c
  177. @@ -77,13 +77,21 @@
  178. #define NF9_IPV6_SRC_ADDR 27
  179. #define NF9_IPV6_DST_ADDR 28
  180. /* ... */
  181. +#define NF9_ICMP_TYPE 32
  182. +/* ... */
  183. #define NF9_SAMPLING_INTERVAL 34
  184. #define NF9_SAMPLING_ALGORITHM 35
  185. /* ... */
  186. +#define NF9_SRC_VLAN 58
  187. +/* ... */
  188. #define NF9_IP_PROTOCOL_VERSION 60
  189. /* Stuff pertaining to the templates that softflowd uses */
  190. -#define NF9_SOFTFLOWD_TEMPLATE_NRECORDS 13
  191. +#ifdef ENABLE_NF9_VLAN
  192. +#define NF9_SOFTFLOWD_TEMPLATE_NRECORDS 16
  193. +#else /* ENABLE_NF9_VLAN */
  194. +#define NF9_SOFTFLOWD_TEMPLATE_NRECORDS 14
  195. +#endif /* ENABLE_NF9_VLAN */
  196. struct NF9_SOFTFLOWD_TEMPLATE {
  197. struct NF9_TEMPLATE_FLOWSET_HEADER h;
  198. struct NF9_TEMPLATE_FLOWSET_RECORD r[NF9_SOFTFLOWD_TEMPLATE_NRECORDS];
  199. @@ -104,6 +112,9 @@
  200. u_int32_t if_index_in, if_index_out;
  201. u_int16_t src_port, dst_port;
  202. u_int8_t protocol, tcp_flags, ipproto, tos;
  203. +#ifdef ENABLE_NF9_VLAN
  204. + u_int16_t icmp_type, vlanid;
  205. +#endif /* ENABLE_NF9_VLAN */
  206. } __packed;
  207. struct NF9_SOFTFLOWD_DATA_V4 {
  208. @@ -185,7 +196,12 @@
  209. v4_template.r[12].length = htons(1);
  210. v4_template.r[13].type = htons(NF9_TOS);
  211. v4_template.r[13].length = htons(1);
  212. -
  213. +#ifdef ENABLE_NF9_VLAN
  214. + v4_template.r[14].type = htons(NF9_ICMP_TYPE);
  215. + v4_template.r[14].length = htons(2);
  216. + v4_template.r[15].type = htons(NF9_SRC_VLAN);
  217. + v4_template.r[15].length = htons(2);
  218. +#endif /* ENABLE_NF9_VLAN */
  219. bzero(&v6_template, sizeof(v6_template));
  220. v6_template.h.c.flowset_id = htons(NF9_TEMPLATE_FLOWSET_ID);
  221. v6_template.h.c.length = htons(sizeof(v6_template));
  222. @@ -219,6 +235,12 @@
  223. v6_template.r[12].length = htons(1);
  224. v6_template.r[13].type = htons(NF9_TOS);
  225. v6_template.r[13].length = htons(1);
  226. +#ifdef ENABLE_NF9_VLAN
  227. + v6_template.r[14].type = htons(NF9_ICMP_TYPE);
  228. + v6_template.r[14].length = htons(2);
  229. + v6_template.r[15].type = htons(NF9_SRC_VLAN);
  230. + v6_template.r[15].length = htons(2);
  231. +#endif /* ENABLE_NF9_VLAN */
  232. }
  233. static void
  234. @@ -298,7 +320,13 @@
  235. dc[1]->tcp_flags = flow->tcp_flags[1];
  236. dc[0]->tos = flow->tos[0];
  237. dc[1]->tos = flow->tos[1];
  238. -
  239. +#ifdef ENABLE_NF9_VLAN
  240. + if (flow->protocol == IPPROTO_ICMP || flow->protocol == IPPROTO_ICMPV6) {
  241. + dc[0]->icmp_type = dc[0]->dst_port;
  242. + dc[1]->icmp_type = dc[1]->dst_port;
  243. + }
  244. + dc[0]->vlanid = dc[1]->vlanid = htons(flow->vlanid);
  245. +#endif /* ENABLE_NF9_VLAN */
  246. if (flow->octets[0] > 0) {
  247. if (ret_len + freclen > len)
  248. return (-1);
  249. @@ -366,16 +394,20 @@
  250. memcpy(packet + offset, &v4_template,
  251. sizeof(v4_template));
  252. offset += sizeof(v4_template);
  253. + nf9->flows++;
  254. memcpy(packet + offset, &v6_template,
  255. sizeof(v6_template));
  256. offset += sizeof(v6_template);
  257. + nf9->flows++;
  258. if (option != NULL && option->sample > 1){
  259. memcpy(packet + offset, &option_template,
  260. sizeof(option_template));
  261. offset += sizeof(option_template);
  262. + nf9->flows++;
  263. memcpy(packet + offset, &option_data,
  264. sizeof(option_data));
  265. offset += sizeof(option_data);
  266. + nf9->flows++;
  267. }
  268. nf9_pkts_until_template = NF9_DEFAULT_TEMPLATE_INTERVAL;
  269. --- a/softflowd.c
  270. +++ b/softflowd.c
  271. @@ -140,6 +140,9 @@
  272. /* Be careful to avoid signed vs unsigned issues here */
  273. int r;
  274. + if (a->vlanid != b->vlanid)
  275. + return (a->vlanid > b->vlanid ? 1 : -1);
  276. +
  277. if (a->af != b->af)
  278. return (a->af > b->af ? 1 : -1);
  279. @@ -336,6 +339,7 @@
  280. flow->port[ndx ^ 1] = udp->uh_dport;
  281. break;
  282. case IPPROTO_ICMP:
  283. + case IPPROTO_ICMPV6:
  284. /*
  285. * Encode ICMP type * 256 + code into dest port like
  286. * Cisco routers
  287. @@ -351,7 +355,7 @@
  288. /* Convert a IPv4 packet to a partial flow record (used for comparison) */
  289. static int
  290. ipv4_to_flowrec(struct FLOW *flow, const u_int8_t *pkt, size_t caplen,
  291. - size_t len, int *isfrag, int af)
  292. + size_t len, int *isfrag, int af, u_int16_t vlanid)
  293. {
  294. const struct ip *ip = (const struct ip *)pkt;
  295. int ndx;
  296. @@ -370,6 +374,7 @@
  297. flow->protocol = ip->ip_p;
  298. flow->octets[ndx] = len;
  299. flow->packets[ndx] = 1;
  300. + flow->vlanid = vlanid;
  301. *isfrag = (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF)) ? 1 : 0;
  302. @@ -384,7 +389,7 @@
  303. /* Convert a IPv6 packet to a partial flow record (used for comparison) */
  304. static int
  305. ipv6_to_flowrec(struct FLOW *flow, const u_int8_t *pkt, size_t caplen,
  306. - size_t len, int *isfrag, int af)
  307. + size_t len, int *isfrag, int af, u_int16_t vlanid)
  308. {
  309. const struct ip6_hdr *ip6 = (const struct ip6_hdr *)pkt;
  310. const struct ip6_ext *eh6;
  311. @@ -407,6 +412,7 @@
  312. flow->addr[ndx ^ 1].v6 = ip6->ip6_dst;
  313. flow->octets[ndx] = len;
  314. flow->packets[ndx] = 1;
  315. + flow->vlanid = vlanid;
  316. *isfrag = 0;
  317. nxt = ip6->ip6_nxt;
  318. @@ -545,7 +551,7 @@
  319. */
  320. static int
  321. process_packet(struct FLOWTRACK *ft, const u_int8_t *pkt, int af,
  322. - const u_int32_t caplen, const u_int32_t len,
  323. + const u_int32_t caplen, const u_int32_t len, u_int16_t vlanid,
  324. const struct timeval *received_time)
  325. {
  326. struct FLOW tmp, *flow;
  327. @@ -557,11 +563,11 @@
  328. memset(&tmp, 0, sizeof(tmp));
  329. switch (af) {
  330. case AF_INET:
  331. - if (ipv4_to_flowrec(&tmp, pkt, caplen, len, &frag, af) == -1)
  332. + if (ipv4_to_flowrec(&tmp, pkt, caplen, len, &frag, af, vlanid) == -1)
  333. goto bad;
  334. break;
  335. case AF_INET6:
  336. - if (ipv6_to_flowrec(&tmp, pkt, caplen, len, &frag, af) == -1)
  337. + if (ipv6_to_flowrec(&tmp, pkt, caplen, len, &frag, af, vlanid) == -1)
  338. goto bad;
  339. break;
  340. default:
  341. @@ -583,6 +589,8 @@
  342. tmp.tcp_flags[0] = tmp.tcp_flags[1] = 0;
  343. /* FALLTHROUGH */
  344. case TRACK_FULL:
  345. + tmp.vlanid = 0;
  346. + case TRACK_FULL_VLAN:
  347. break;
  348. }
  349. @@ -1073,10 +1081,12 @@
  350. * packet should be skipped
  351. */
  352. static int
  353. -datalink_check(int linktype, const u_int8_t *pkt, u_int32_t caplen, int *af)
  354. +datalink_check(int linktype, const u_int8_t *pkt, u_int32_t caplen, int *af, u_int16_t *vlanid)
  355. {
  356. int i, j;
  357. u_int32_t frametype;
  358. + int add_offset = 0;
  359. +
  360. static const struct DATALINK *dl = NULL;
  361. /* Try to cache last used linktype */
  362. @@ -1092,15 +1102,24 @@
  363. /* Suck out the frametype */
  364. frametype = 0;
  365. +
  366. + /* Processing 802.1Q vlan in ethernet */
  367. + if (linktype == DLT_EN10MB && ntohs(*(u_int16_t *)(pkt + dl->ft_off)) == 0x8100) {
  368. + add_offset = 4;
  369. + if (caplen <= dl->skiplen + add_offset)
  370. + return (-1);
  371. + *vlanid = ntohs(*(u_int16_t *)(pkt + dl->ft_off + 2)) & 0x0fff;
  372. + }
  373. +
  374. if (dl->ft_is_be) {
  375. for (j = 0; j < dl->ft_len; j++) {
  376. frametype <<= 8;
  377. - frametype |= pkt[j + dl->ft_off];
  378. + frametype |= pkt[j + dl->ft_off + add_offset];
  379. }
  380. } else {
  381. for (j = dl->ft_len - 1; j >= 0 ; j--) {
  382. frametype <<= 8;
  383. - frametype |= pkt[j + dl->ft_off];
  384. + frametype |= pkt[j + dl->ft_off + add_offset];
  385. }
  386. }
  387. frametype &= dl->ft_mask;
  388. @@ -1112,7 +1131,7 @@
  389. else
  390. return (-1);
  391. - return (dl->skiplen);
  392. + return (dl->skiplen + add_offset);
  393. }
  394. /*
  395. @@ -1123,9 +1142,10 @@
  396. flow_cb(u_char *user_data, const struct pcap_pkthdr* phdr,
  397. const u_char *pkt)
  398. {
  399. - int s, af;
  400. + int s, af = 0;
  401. struct CB_CTXT *cb_ctxt = (struct CB_CTXT *)user_data;
  402. struct timeval tv;
  403. + u_int16_t vlanid = 0;
  404. if (cb_ctxt->ft->param.option.sample &&
  405. (cb_ctxt->ft->param.total_packets +
  406. @@ -1134,14 +1154,14 @@
  407. cb_ctxt->ft->param.non_sampled_packets++;
  408. return;
  409. }
  410. - s = datalink_check(cb_ctxt->linktype, pkt, phdr->caplen, &af);
  411. + s = datalink_check(cb_ctxt->linktype, pkt, phdr->caplen, &af, &vlanid);
  412. if (s < 0 || (!cb_ctxt->want_v6 && af == AF_INET6)) {
  413. cb_ctxt->ft->param.non_ip_packets++;
  414. } else {
  415. tv.tv_sec = phdr->ts.tv_sec;
  416. tv.tv_usec = phdr->ts.tv_usec;
  417. - if (process_packet(cb_ctxt->ft, pkt + s, af,
  418. - phdr->caplen - s, phdr->len - s, &tv) == PP_MALLOC_FAIL)
  419. + if (process_packet(cb_ctxt->ft, pkt + s, af, phdr->caplen - s,
  420. + phdr->len - s, vlanid, &tv) == PP_MALLOC_FAIL)
  421. cb_ctxt->fatal = 1;
  422. }
  423. }
  424. @@ -1393,7 +1413,7 @@
  425. bpf_net = bpf_mask = 0;
  426. }
  427. *linktype = pcap_datalink(*pcap);
  428. - if (datalink_check(*linktype, NULL, 0, NULL) == -1) {
  429. + if (datalink_check(*linktype, NULL, 0, NULL, NULL) == -1) {
  430. fprintf(stderr, "Unsupported datalink type %d\n", *linktype);
  431. exit(1);
  432. }
  433. @@ -1496,14 +1516,14 @@
  434. " -c pidfile Location of control socket\n"
  435. " (default: %s)\n"
  436. " -v 1|5|9|10 NetFlow export packet version\n"
  437. -" (10 means IPFI)\n"
  438. +" (10 means IPFIX)\n"
  439. " -L hoplimit Set TTL/hoplimit for export datagrams\n"
  440. -" -T full|port|proto|ip Set flow tracking level (default: full)\n"
  441. +" -T full|port|proto|ip| Set flow tracking level (default: full)\n"
  442. +" vlan (\"vlan\" tracking means \"full\" tracking with vlanid)\n"
  443. " -6 Track IPv6 flows, regardless of whether selected \n"
  444. " NetFlow export protocol supports it\n"
  445. " -d Don't daemonise (run in foreground)\n"
  446. " -D Debug mode: foreground + verbosity + track v6 flows\n"
  447. -" -s sampling_rate Specify periodical sampling rate (denominator)\n"
  448. " -P udp|tcp|sctp Specify transport layer protocol for exporting packets\n"
  449. " -A sec|milli|micro|nano Specify absolute time format form exporting records\n"
  450. " -s sampling_rate Specify periodical sampling rate (denominator)\n"
  451. @@ -1777,6 +1797,8 @@
  452. flowtrack.param.track_level = TRACK_IP_PROTO;
  453. else if (strcasecmp(optarg, "ip") == 0)
  454. flowtrack.param.track_level = TRACK_IP_ONLY;
  455. + else if (strcasecmp(optarg, "vlan") == 0)
  456. + flowtrack.param.track_level = TRACK_FULL_VLAN;
  457. else {
  458. fprintf(stderr, "Unknown flow tracking "
  459. "level\n");
  460. --- a/softflowd.h
  461. +++ b/softflowd.h
  462. @@ -73,6 +73,7 @@
  463. #define TRACK_IP_PROTO_PORT 2 /* src/dst/addr/port/proto 5-tuple */
  464. #define TRACK_IP_PROTO 3 /* src/dst/proto 3-tuple */
  465. #define TRACK_IP_ONLY 4 /* src/dst tuple */
  466. +#define TRACK_FULL_VLAN 5 /* src/dst/addr/port/proto/tos/vlanid 7-tuple */
  467. /*
  468. * This structure contains optional information carried by Option Data
  469. @@ -187,6 +188,7 @@
  470. u_int16_t port[2]; /* Endpoint ports */
  471. u_int8_t tcp_flags[2]; /* Cumulative OR of flags */
  472. u_int8_t tos[2]; /* Tos */
  473. + u_int16_t vlanid; /* vlanid */
  474. u_int8_t protocol; /* Protocol */
  475. };
  476. @@ -234,5 +236,6 @@
  477. /* Force a resend of the flow template */
  478. void netflow9_resend_template(void);
  479. +void ipfix_resend_template(void);
  480. #endif /* _SOFTFLOWD_H */