static int meta_fill(struct rtnl_ematch *e, struct nl_msg *msg) { struct meta_data *m = rtnl_ematch_data(e); struct tcf_meta_hdr hdr; if (!(m->left && m->right)) return -NLE_MISSING_ATTR; memset(&hdr, 0, sizeof(hdr)); hdr.left.kind = (m->left->mv_type << 12) & TCF_META_TYPE_MASK; hdr.left.kind |= m->left->mv_id & TCF_META_ID_MASK; hdr.left.shift = m->left->mv_shift; hdr.left.op = m->opnd; hdr.right.kind = (m->right->mv_type << 12) & TCF_META_TYPE_MASK; hdr.right.kind |= m->right->mv_id & TCF_META_ID_MASK; NLA_PUT(msg, TCA_EM_META_HDR, sizeof(hdr), &hdr); if (m->left->mv_len) NLA_PUT(msg, TCA_EM_META_LVALUE, m->left->mv_len, (m->left + 1)); if (m->right->mv_len) NLA_PUT(msg, TCA_EM_META_RVALUE, m->right->mv_len, (m->right + 1)); return 0; nla_put_failure: return -NLE_NOMEM; }
void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer, uint16_t offset) { struct nbyte_data *n = rtnl_ematch_data(e); n->cfg.off = offset; n->cfg.layer = layer; }
void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e, uint8_t *pattern, size_t len) { struct nbyte_data *n = rtnl_ematch_data(e); if (n->pattern) free(n->pattern); n->pattern = pattern; n->cfg.len = len; }
static void meta_dump(struct rtnl_ematch *e, struct nl_dump_params *p) { struct meta_data *m = rtnl_ematch_data(e); char buf[32]; nl_dump(p, "meta("); dump_value(m->left, p); nl_dump(p, " %s ", rtnl_ematch_opnd2txt(m->opnd, buf, sizeof(buf))); dump_value(m->right, p); nl_dump(p, ")"); }
static int meta_parse(struct rtnl_ematch *e, void *data, size_t len) { struct meta_data *m = rtnl_ematch_data(e); struct nlattr *tb[TCA_EM_META_MAX+1]; struct rtnl_meta_value *v; struct tcf_meta_hdr *hdr; void *vdata = NULL; size_t vlen = 0; int err; if ((err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy)) < 0) return err; if (!tb[TCA_EM_META_HDR]) return -NLE_MISSING_ATTR; hdr = nla_data(tb[TCA_EM_META_HDR]); if (tb[TCA_EM_META_LVALUE]) { vdata = nla_data(tb[TCA_EM_META_LVALUE]); vlen = nla_len(tb[TCA_EM_META_LVALUE]); } v = meta_alloc(TCF_META_TYPE(hdr->left.kind), TCF_META_ID(hdr->left.kind), hdr->left.shift, vdata, vlen); if (!v) return -NLE_NOMEM; m->left = v; vlen = 0; if (tb[TCA_EM_META_RVALUE]) { vdata = nla_data(tb[TCA_EM_META_RVALUE]); vlen = nla_len(tb[TCA_EM_META_RVALUE]); } v = meta_alloc(TCF_META_TYPE(hdr->right.kind), TCF_META_ID(hdr->right.kind), hdr->right.shift, vdata, vlen); if (!v) { rtnl_meta_value_put(m->left); return -NLE_NOMEM; } m->right = v; m->opnd = hdr->left.op; return 0; }
static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p) { struct nbyte_data *n = rtnl_ematch_data(e); int i; nl_dump(p, "pattern(%u:[", n->cfg.len); for (i = 0; i < n->cfg.len; i++) { nl_dump(p, "%02x", n->pattern[i]); if (i+1 < n->cfg.len) nl_dump(p, " "); } nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off); }
static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len) { struct nbyte_data *n = rtnl_ematch_data(e); size_t hdrlen = sizeof(struct tcf_em_nbyte); size_t plen = len - hdrlen; memcpy(&n->cfg, data, hdrlen); if (plen > 0) { if (!(n->pattern = calloc(1, plen))) return -NLE_NOMEM; memcpy(n->pattern, data + hdrlen, plen); } return 0; }
static void cmp_dump(struct rtnl_ematch *e, struct nl_dump_params *p) { struct tcf_em_cmp *cmp = rtnl_ematch_data(e); if (cmp->flags & TCF_EM_CMP_TRANS) nl_dump(p, "ntoh%c(", (cmp->align == TCF_EM_ALIGN_U32) ? 'l' : 's'); nl_dump(p, "%s at %s+%u", align_txt[cmp->align], layer_txt[cmp->layer], cmp->off); if (cmp->mask) nl_dump(p, " & 0x%x", cmp->mask); if (cmp->flags & TCF_EM_CMP_TRANS) nl_dump(p, ")"); nl_dump(p, " %s %u", operand_txt[cmp->opnd], cmp->val); }
static inline uint32_t container_ref(struct rtnl_ematch *ematch) { return *((uint32_t *) rtnl_ematch_data(ematch)); }
static int cmp_parse(struct rtnl_ematch *e, void *data, size_t len) { memcpy(rtnl_ematch_data(e), data, len); return 0; }
struct tcf_em_cmp *rtnl_ematch_cmp_get(struct rtnl_ematch *e) { return rtnl_ematch_data(e); }
void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg) { memcpy(rtnl_ematch_data(e), cfg, sizeof(*cfg)); }
void rtnl_ematch_meta_set_rvalue(struct rtnl_ematch *e, struct rtnl_meta_value *v) { struct meta_data *m = rtnl_ematch_data(e); m->right = v; }
static void meta_free(struct rtnl_ematch *e) { struct meta_data *m = rtnl_ematch_data(e); free(m->left); free(m->right); }
uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e) { return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off; }
uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e) { return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer; }
static void nbyte_free(struct rtnl_ematch *e) { struct nbyte_data *n = rtnl_ematch_data(e); free(n->pattern); }
void rtnl_ematch_meta_set_operand(struct rtnl_ematch *e, uint8_t opnd) { struct meta_data *m = rtnl_ematch_data(e); m->opnd = opnd; }
size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e) { return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len; }
uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e) { return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern; }