int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset) { struct rtnl_u32 *u; struct tc_u32_sel *sel; int err; hashmask = htonl(hashmask); if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); if(err < 0) return err; sel = u32_selector(u); sel->hmask = hashmask; sel->hoff = offset; return 0; }
/** * Append new 32-bit key to the selector * * @arg cls classifier to be modifier * @arg val value to be matched (network byte-order) * @arg mask mask to be applied before matching (network byte-order) * @arg off offset, in bytes, to start matching * @arg offmask offset mask * * General selectors define the pattern, mask and offset the pattern will be * matched to the packet contents. Using the general selectors you can match * virtually any single bit in the IP (or upper layer) header. * */ int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, int off, int offmask) { struct tc_u32_sel *sel; struct rtnl_u32 *u; int err; if (!(u = rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; if (sel->nkeys == UCHAR_MAX) return -NLE_NOMEM; err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); if (err < 0) return err; /* the selector might have been moved by realloc */ sel = u32_selector(u); sel->keys[sel->nkeys].mask = mask; sel->keys[sel->nkeys].val = val & mask; sel->keys[sel->nkeys].off = off; sel->keys[sel->nkeys].offmask = offmask; sel->nkeys++; u->cu_mask |= U32_ATTR_SELECTOR; return 0; }
int rtnl_u32_set_flags(struct rtnl_cls *cls, int flags) { struct tc_u32_sel *sel; struct rtnl_u32 *u = rtnl_cls_data(cls); sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; sel->flags |= flags; u->cu_mask |= U32_ATTR_SELECTOR; return 0; }
int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) { struct rtnl_u32 *u; struct tc_u32_sel *sel; if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; sel->flags |= TC_U32_TERMINAL; return 0; }
int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset) { struct rtnl_u32 *u; struct tc_u32_sel *sel; hashmask = htonl(hashmask); if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; sel->hmask = hashmask; sel->hoff = offset; return 0; }
int rtnl_u32_set_selector(struct rtnl_cls *cls, int offoff, uint32_t offmask, char offshift, uint16_t off, char flags) { struct rtnl_u32 *u; struct tc_u32_sel *sel; offmask = ntohs(offmask); if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; sel->offoff = offoff; sel->offmask = offmask; sel->offshift = offshift; sel->flags |= TC_U32_VAROFFSET; sel->off = off; sel->flags |= flags; return 0; }
int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls) { struct rtnl_u32 *u; struct tc_u32_sel *sel; int err; if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; sel = u32_selector_alloc(u); if (!sel) return -NLE_NOMEM; err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); if(err < 0) return err; sel = u32_selector(u); sel->flags |= TC_U32_TERMINAL; return 0; }