int nf9_rec_to_flow(u_int record_type, u_int record_length, u_int8_t *data, simple_packet& packet) {
        /* XXX: use a table-based interpreter */
        switch (record_type) {

/* Copy an int (possibly shorter than the target) keeping their LSBs aligned */
#define BE_COPY(a) memcpy((u_char*)&a + (sizeof(a) - record_length), data, record_length);

#define V9_FIELD(v9_field, store_field, flow_field) \
        case v9_field: \
                BE_COPY(packet.flow_field); \
                break
#define V9_FIELD_ADDR(v9_field, store_field, flow_field) \
        case v9_field: \
                memcpy(&packet.flow_field, data, record_length); \
                break
        V9_FIELD(NF9_IN_BYTES,    OCTETS,           length);
        V9_FIELD(NF9_IN_PACKETS,  PACKETS,          number_of_packets);
        V9_FIELD(NF9_IN_PROTOCOL, PROTO_FLAGS_TOS,  protocol);
        V9_FIELD(NF9_TCP_FLAGS,   PROTO_FLAGS_TOS,  flags);
        V9_FIELD(NF9_L4_SRC_PORT, SRCDST_PORT,      source_port);
        V9_FIELD(NF9_L4_DST_PORT, SRCDST_PORT,      destination_port);
      
        V9_FIELD_ADDR(NF9_IPV4_SRC_ADDR, SRC_ADDR4, src_ip);
        V9_FIELD_ADDR(NF9_IPV4_DST_ADDR, DST_ADDR4, dst_ip);

	// Sampling rate
	// We use NULL as second argument because it's suelles for us
	// It did not help us because looks like sampling rate implemented with OPTIONS flowset
	// V9_FIELD(NF9_SAMPLING_INTERVAL, NULL, sample_ratio);

        //V9_FIELD(NF9_SRC_TOS, PROTO_FLAGS_TOS, pft.tos);
        //V9_FIELD(NF9_SRC_MASK, AS_INFO, asinf.src_mask);
        //V9_FIELD(NF9_INPUT_SNMP, IF_INDICES, ifndx.if_index_in);
        //V9_FIELD(NF9_DST_MASK, AS_INFO, asinf.dst_mask);
        //V9_FIELD(NF9_OUTPUT_SNMP, IF_INDICES, ifndx.if_index_out);
        //V9_FIELD(NF9_SRC_AS, AS_INFO, asinf.src_as);
        //V9_FIELD(NF9_DST_AS, AS_INFO, asinf.dst_as);
        //V9_FIELD(NF9_LAST_SWITCHED, FLOW_TIMES, ftimes.flow_finish);
        //V9_FIELD(NF9_FIRST_SWITCHED, FLOW_TIMES, ftimes.flow_start);
        //V9_FIELD(NF9_IPV6_SRC_MASK, AS_INFO, asinf.src_mask);
        //V9_FIELD(NF9_IPV6_DST_MASK, AS_INFO, asinf.dst_mask);
        //V9_FIELD(NF9_ENGINE_TYPE, FLOW_ENGINE_INFO, finf.engine_type);
        //V9_FIELD(NF9_ENGINE_ID, FLOW_ENGINE_INFO, finf.engine_id);
        //V9_FIELD_ADDR(NF9_IPV4_NEXT_HOP, GATEWAY_ADDR4, gateway_addr, 4, INET);
        //V9_FIELD_ADDR(NF9_IPV6_SRC_ADDR, SRC_ADDR6, src_addr, 6, INET6);
        //V9_FIELD_ADDR(NF9_IPV6_DST_ADDR, DST_ADDR6, dst_addr, 6, INET6);
        //V9_FIELD_ADDR(NF9_IPV6_NEXT_HOP, GATEWAY_ADDR6, gateway_addr, 6, INET6);

//#undef V9_FIELD
//#undef V9_FIELD_ADDR
//#undef BE_COPY
        }
        return 0;
}
int nf10_rec_to_flow(u_int record_type, u_int record_length, u_int8_t *data, simple_packet& packet) { 
    /* XXX: use a table-based interpreter */
    switch (record_type) {
        V9_FIELD(NF10_IN_BYTES,    OCTETS,           length);
        V9_FIELD(NF10_IN_PACKETS,  PACKETS,          number_of_packets);
        V9_FIELD(NF10_IN_PROTOCOL, PROTO_FLAGS_TOS,  protocol);
        V9_FIELD(NF10_TCP_FLAGS,   PROTO_FLAGS_TOS,  flags);
        V9_FIELD(NF10_L4_SRC_PORT, SRCDST_PORT,      source_port);
        V9_FIELD(NF10_L4_DST_PORT, SRCDST_PORT,      destination_port);
      
        V9_FIELD_ADDR(NF10_IPV4_SRC_ADDR, SRC_ADDR4, src_ip);
        V9_FIELD_ADDR(NF10_IPV4_DST_ADDR, DST_ADDR4, dst_ip);
    }

    return 0;
}
static int
nf9_rec_to_flow(struct peer_nf9_record *rec, struct store_flow_complete *flow,
    u_int8_t *data)
{
	/* XXX: use a table-based interpreter */
	switch (rec->type) {

/* Copy an int (possibly shorter than the target) keeping their LSBs aligned */
#define BE_COPY(a) memcpy((u_char*)&a + (sizeof(a) - rec->len), data, rec->len);
#define V9_FIELD(v9_field, store_field, flow_field) \
	case v9_field: \
		flow->hdr.fields |= STORE_FIELD_##store_field; \
		BE_COPY(flow->flow_field); \
		break
#define V9_FIELD_ADDR(v9_field, store_field, flow_field, sub, family) \
	case v9_field: \
		flow->hdr.fields |= STORE_FIELD_##store_field; \
		memcpy(&flow->flow_field.v##sub, data, rec->len); \
		flow->flow_field.af = AF_##family; \
		break

	V9_FIELD(NF9_IN_BYTES, OCTETS, octets.flow_octets);
	V9_FIELD(NF9_IN_PACKETS, PACKETS, packets.flow_packets);
	V9_FIELD(NF9_IN_PROTOCOL, PROTO_FLAGS_TOS, pft.protocol);
	V9_FIELD(NF9_SRC_TOS, PROTO_FLAGS_TOS, pft.tos);
	V9_FIELD(NF9_TCP_FLAGS, PROTO_FLAGS_TOS, pft.tcp_flags);
	V9_FIELD(NF9_L4_SRC_PORT, SRCDST_PORT, ports.src_port);
	V9_FIELD(NF9_SRC_MASK, AS_INFO, asinf.src_mask);
	V9_FIELD(NF9_INPUT_SNMP, IF_INDICES, ifndx.if_index_in);
	V9_FIELD(NF9_L4_DST_PORT, SRCDST_PORT, ports.dst_port);
	V9_FIELD(NF9_DST_MASK, AS_INFO, asinf.dst_mask);
	V9_FIELD(NF9_OUTPUT_SNMP, IF_INDICES, ifndx.if_index_out);
	V9_FIELD(NF9_SRC_AS, AS_INFO, asinf.src_as);
	V9_FIELD(NF9_DST_AS, AS_INFO, asinf.dst_as);
	V9_FIELD(NF9_LAST_SWITCHED, FLOW_TIMES, ftimes.flow_finish);
	V9_FIELD(NF9_FIRST_SWITCHED, FLOW_TIMES, ftimes.flow_start);
	V9_FIELD(NF9_IPV6_SRC_MASK, AS_INFO, asinf.src_mask);
	V9_FIELD(NF9_IPV6_DST_MASK, AS_INFO, asinf.dst_mask);
	V9_FIELD(NF9_ENGINE_TYPE, FLOW_ENGINE_INFO, finf.engine_type);
	V9_FIELD(NF9_ENGINE_ID, FLOW_ENGINE_INFO, finf.engine_id);

	V9_FIELD_ADDR(NF9_IPV4_SRC_ADDR, SRC_ADDR4, src_addr, 4, INET);
	V9_FIELD_ADDR(NF9_IPV4_DST_ADDR, DST_ADDR4, dst_addr, 4, INET);
	V9_FIELD_ADDR(NF9_IPV4_NEXT_HOP, GATEWAY_ADDR4, gateway_addr, 4, INET);

	V9_FIELD_ADDR(NF9_IPV6_SRC_ADDR, SRC_ADDR6, src_addr, 6, INET6);
	V9_FIELD_ADDR(NF9_IPV6_DST_ADDR, DST_ADDR6, dst_addr, 6, INET6);
	V9_FIELD_ADDR(NF9_IPV6_NEXT_HOP, GATEWAY_ADDR6, gateway_addr, 6, INET6);

#undef V9_FIELD
#undef V9_FIELD_ADDR
#undef BE_COPY
	}
	return (0);
}
int nf9_rec_to_flow(u_int record_type, u_int record_length, u_int8_t* data, simple_packet& packet) {
    /* XXX: use a table-based interpreter */
    switch (record_type) {
        V9_FIELD(NF9_IN_BYTES, OCTETS, length);
        V9_FIELD(NF9_IN_PACKETS, PACKETS, number_of_packets);
        V9_FIELD(NF9_IN_PROTOCOL, PROTO_FLAGS_TOS, protocol);
        V9_FIELD(NF9_TCP_FLAGS, PROTO_FLAGS_TOS, flags);
        V9_FIELD(NF9_L4_SRC_PORT, SRCDST_PORT, source_port);
        V9_FIELD(NF9_L4_DST_PORT, SRCDST_PORT, destination_port);

        case NF9_IPV4_SRC_ADDR:
            memcpy(&packet.src_ip, data, record_length);
            break;
        case NF9_IPV4_DST_ADDR:
            memcpy(&packet.dst_ip, data, record_length);
            break;
        case NF9_INPUT_SNMP: {
                // TODO: port number could be 4 byte (Juniper MX) and we should rewrite BE_COPY for correct handling
                uint16_t input_port = 0;

                if (record_length > sizeof(input_port)) {
                    //logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_INPUT_SNMP!";
                    //return 0;
                } else {
                    BE_COPY(input_port);
                    input_port = fast_ntoh(input_port);
                    // logger << log4cpp::Priority::INFO << "NF9_INPUT_SNMP is: " << input_port;
                }
            }

            break;
        case NF9_OUTPUT_SNMP: {
                uint16_t output_port = 0; 

                if (record_length > sizeof(output_port)) {
                    //logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_OUTPUT_SNMP!";
                    //return 0;
                } else {
                    BE_COPY(output_port);
                    output_port = fast_ntoh(output_port);
                    // logger << log4cpp::Priority::INFO << "NF9_OUTPUT_SNMP is: " << output_port;
                }
            }    

            break;        


        //V9_FIELD_ADDR(NF9_IPV4_SRC_ADDR, SRC_ADDR4, src_ip);
        //V9_FIELD_ADDR(NF9_IPV4_DST_ADDR, DST_ADDR4, dst_ip);

        // Sampling rate
        // We use NULL as second argument because it's suelles for us
        // It did not help us because looks like sampling rate implemented with OPTIONS flowset
        // V9_FIELD(NF9_SAMPLING_INTERVAL, NULL, sample_ratio);

        // V9_FIELD(NF9_SRC_TOS, PROTO_FLAGS_TOS, pft.tos);
        // V9_FIELD(NF9_SRC_MASK, AS_INFO, asinf.src_mask);
        // V9_FIELD(NF9_INPUT_SNMP, IF_INDICES, ifndx.if_index_in);
        // V9_FIELD(NF9_DST_MASK, AS_INFO, asinf.dst_mask);
        // V9_FIELD(NF9_OUTPUT_SNMP, IF_INDICES, ifndx.if_index_out);
        // V9_FIELD(NF9_SRC_AS, AS_INFO, asinf.src_as);
        // V9_FIELD(NF9_DST_AS, AS_INFO, asinf.dst_as);
        // V9_FIELD(NF9_LAST_SWITCHED, FLOW_TIMES, ftimes.flow_finish);
        // V9_FIELD(NF9_FIRST_SWITCHED, FLOW_TIMES, ftimes.flow_start);
        // V9_FIELD(NF9_IPV6_SRC_MASK, AS_INFO, asinf.src_mask);
        // V9_FIELD(NF9_IPV6_DST_MASK, AS_INFO, asinf.dst_mask);
        // V9_FIELD(NF9_ENGINE_TYPE, FLOW_ENGINE_INFO, finf.engine_type);
        // V9_FIELD(NF9_ENGINE_ID, FLOW_ENGINE_INFO, finf.engine_id);
        // V9_FIELD_ADDR(NF9_IPV4_NEXT_HOP, GATEWAY_ADDR4, gateway_addr, 4, INET);
        // V9_FIELD_ADDR(NF9_IPV6_SRC_ADDR, SRC_ADDR6, src_addr, 6, INET6);
        // V9_FIELD_ADDR(NF9_IPV6_DST_ADDR, DST_ADDR6, dst_addr, 6, INET6);
        // V9_FIELD_ADDR(NF9_IPV6_NEXT_HOP, GATEWAY_ADDR6, gateway_addr, 6, INET6);

        //#undef V9_FIELD
        //#undef V9_FIELD_ADDR
        //#undef BE_COPY
    }

    return 0;
}