format_mpls(struct ds *ds, const struct ovs_key_mpls *mpls_key,
const struct ovs_key_mpls *mpls_mask, int n)
{
- if (n == 1) {
- ovs_be32 key = mpls_key->mpls_lse;
+ for (int i = 0; i < n; i++) {
+ ovs_be32 key = mpls_key[i].mpls_lse;
if (mpls_mask == NULL) {
format_mpls_lse(ds, key);
} else {
- ovs_be32 mask = mpls_mask->mpls_lse;
+ ovs_be32 mask = mpls_mask[i].mpls_lse;
ds_put_format(ds, "label=%"PRIu32"/0x%x,tc=%d/%x,ttl=%d/0x%x,bos=%d/%x",
mpls_lse_to_label(key), mpls_lse_to_label(mask),
mpls_lse_to_ttl(key), mpls_lse_to_ttl(mask),
mpls_lse_to_bos(key), mpls_lse_to_bos(mask));
}
- } else {
- int i;
-
- for (i = 0; i < n; i++) {
- ds_put_format(ds, "lse%d=%#"PRIx32,
- i, ntohl(mpls_key[i].mpls_lse));
- if (mpls_mask) {
- ds_put_format(ds, "/%#"PRIx32, ntohl(mpls_mask[i].mpls_lse));
- }
- ds_put_char(ds, ',');
- }
- ds_chomp(ds, ',');
+ ds_put_char(ds, ',');
}
+ ds_chomp(ds, ',');
}
static void
IP_ARGS(get_16aligned_be32(&ip->ip_dst)),
ip->ip_proto, ip->ip_tos,
ip->ip_ttl,
- ip->ip_frag_off);
+ ntohs(ip->ip_frag_off));
l4 = (ip + 1);
} else {
const struct ip6_hdr *ip6;
if (eth->eth_type == htons(ETH_TYPE_IP)) {
/* IPv4 */
+ uint16_t ip_frag_off;
if (!ovs_scan_len(s, &n, "ipv4(src="IP_SCAN_FMT",dst="IP_SCAN_FMT",proto=%"SCNi8
",tos=%"SCNi8",ttl=%"SCNi8",frag=0x%"SCNx16"),",
IP_SCAN_ARGS(&sip),
IP_SCAN_ARGS(&dip),
&ip->ip_proto, &ip->ip_tos,
- &ip->ip_ttl, &ip->ip_frag_off)) {
+ &ip->ip_ttl, &ip_frag_off)) {
return -EINVAL;
}
put_16aligned_be32(&ip->ip_src, sip);
put_16aligned_be32(&ip->ip_dst, dip);
+ ip->ip_frag_off = htons(ip_frag_off);
ip_len = sizeof *ip;
} else {
char sip6_s[IPV6_SCAN_LEN + 1];
return s - start; \
}
+#define SCAN_BEGIN_ARRAY(NAME, TYPE, CNT) \
+ SCAN_IF(NAME); \
+ TYPE skey[CNT], smask[CNT]; \
+ memset(&skey, 0, sizeof skey); \
+ memset(&smask, 0, sizeof smask); \
+ int idx = 0, cnt = CNT; \
+ uint64_t fields = 0; \
+ do { \
+ int field = 0; \
+ len = 0;
+
+/* Scan named ('NAME') entry 'FIELD' as 'TYPE'. */
+#define SCAN_FIELD_ARRAY(NAME, TYPE, FIELD) \
+ if (strncmp(s, NAME, strlen(NAME)) == 0) { \
+ if (fields & (1UL << field)) { \
+ fields = 0; \
+ if (++idx == cnt) { \
+ break; \
+ } \
+ } \
+ s += strlen(NAME); \
+ SCAN_TYPE(TYPE, &skey[idx].FIELD, mask ? &smask[idx].FIELD : NULL); \
+ fields |= 1UL << field; \
+ continue; \
+ } \
+ field++;
+
+#define SCAN_PUT_ATTR_ARRAY(BUF, ATTR, DATA, CNT) \
+ nl_msg_put_unspec(BUF, ATTR, &(DATA), sizeof (DATA)[0] * (CNT)); \
+
+#define SCAN_PUT_ARRAY(ATTR, CNT) \
+ SCAN_PUT_ATTR_ARRAY(key, ATTR, skey, CNT); \
+ if (mask) { \
+ SCAN_PUT_ATTR_ARRAY(mask, ATTR, smask, CNT); \
+ }
+
+#define SCAN_END_ARRAY(ATTR) \
+ SCAN_FINISH(); \
+ if (idx == cnt) { \
+ return -EINVAL; \
+ } \
+ SCAN_PUT_ARRAY(ATTR, idx + 1); \
+ return s - start; \
+ }
+
#define SCAN_END_SINGLE(ATTR) \
SCAN_FINISH_SINGLE(); \
SCAN_PUT(ATTR, NULL); \
SCAN_SINGLE("eth_type(", ovs_be16, be16, OVS_KEY_ATTR_ETHERTYPE);
- SCAN_BEGIN("mpls(", struct ovs_key_mpls) {
- SCAN_FIELD("label=", mpls_label, mpls_lse);
- SCAN_FIELD("tc=", mpls_tc, mpls_lse);
- SCAN_FIELD("ttl=", mpls_ttl, mpls_lse);
- SCAN_FIELD("bos=", mpls_bos, mpls_lse);
- } SCAN_END(OVS_KEY_ATTR_MPLS);
+ SCAN_BEGIN_ARRAY("mpls(", struct ovs_key_mpls, FLOW_MAX_MPLS_LABELS) {
+ SCAN_FIELD_ARRAY("label=", mpls_label, mpls_lse);
+ SCAN_FIELD_ARRAY("tc=", mpls_tc, mpls_lse);
+ SCAN_FIELD_ARRAY("ttl=", mpls_ttl, mpls_lse);
+ SCAN_FIELD_ARRAY("bos=", mpls_bos, mpls_lse);
+ } SCAN_END_ARRAY(OVS_KEY_ATTR_MPLS);
SCAN_BEGIN("ipv4(", struct ovs_key_ipv4) {
SCAN_FIELD("src=", ipv4, ipv4_src);