| ICMP CODE { $$ = FLOW_TYPE_ICMP_CODE; }
| LENGTH { $$ = FLOW_TYPE_PACKET_LENGTH; }
| DSCP { $$ = FLOW_TYPE_DSCP; }
- | LABEL { $$ = FLOW_TYPE_LABEL; }
+ | LABEL { $$ = FLOW_TYPE_LABEL; if (!this_flow->ipv6) cf_error("Flow label not valid in flow4"); }
;
flow_num_type: flow_num_type_{ flow_builder_set_type(this_flow, $1); };
;
flow_frag_val:
- DONT_FRAGMENT { $$ = 1; }
+ DONT_FRAGMENT { $$ = 1; if (this_flow->ipv6) cf_error("Flag dont_fragment not valid in flow6"); }
| IS_FRAGMENT { $$ = 2; }
| FIRST_FRAGMENT { $$ = 4; }
| LAST_FRAGMENT { $$ = 8; }
[FLOW_TYPE_FRAGMENT] = 1,
};
-/* Maximum valid numeric values (in bytes), semantically */
+/* Maximum valid numeric values (in bits), semantically */
static const u8 flow_max_valid_value[FLOW_TYPE_MAX] = {
- [FLOW_TYPE_IP_PROTOCOL] = 1,
- [FLOW_TYPE_PORT] = 2,
- [FLOW_TYPE_DST_PORT] = 2,
- [FLOW_TYPE_SRC_PORT] = 2,
- [FLOW_TYPE_ICMP_TYPE] = 1,
- [FLOW_TYPE_ICMP_CODE] = 1,
- [FLOW_TYPE_PACKET_LENGTH] = 2,
- [FLOW_TYPE_DSCP] = 1,
- [FLOW_TYPE_LABEL] = 4,
+ [FLOW_TYPE_IP_PROTOCOL] = 8,
+ [FLOW_TYPE_PORT] = 16,
+ [FLOW_TYPE_DST_PORT] = 16,
+ [FLOW_TYPE_SRC_PORT] = 16,
+ [FLOW_TYPE_ICMP_TYPE] = 8,
+ [FLOW_TYPE_ICMP_CODE] = 8,
+ [FLOW_TYPE_PACKET_LENGTH] = 16,
+ [FLOW_TYPE_DSCP] = 6,
+ [FLOW_TYPE_LABEL] = 20,
};
/**
flow_check_cf_numeric_arg(struct flow_builder *fb, uint val)
{
enum flow_type t = fb->this_type;
- uint max = flow_max_valid_value[t];
-
- if (t == FLOW_TYPE_DSCP && val > 0x3f)
- cf_error("%s value %u out of range (0-63)", flow_type_str(t, fb->ipv6), val);
-
- if (max == 1 && (val > 0xff))
- cf_error("%s value %u out of range (0-255)", flow_type_str(t, fb->ipv6), val);
+ u64 max = (U64(1) << flow_max_valid_value[t]) - 1;
- if (max == 2 && (val > 0xffff))
- cf_error("%s value %u out of range (0-65535)", flow_type_str(t, fb->ipv6), val);
+ if (max && (val > max))
+ cf_error("%s value %u out of range (0-%lu)", flow_type_str(t, fb->ipv6), val, max);
}
/* Bitmask of padding bits in last byte of prefix */