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
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, 3) {
+ 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);
])
dnl Double MPLS pop
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=60,tc=0,ttl=64,bos=0)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=60,tc=0,ttl=64,bos=0,label=50,tc=0,ttl=64,bos=1)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: pop_mpls(eth_type=0x8847),recirc(0x1)
])