144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/cls/u32.c u32 classifier 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 9ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2005-2006 Petr Gotthard <petr.gotthard@siemens.com> 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2005-2006 Siemens AG Oesterreich 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup cls_api 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup u32 Universal 32-bit Classifier 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-tc.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/attr.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/tc.h> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/classifier.h> 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/classifier-modules.h> 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/cls/u32.h> 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_DIVISOR 0x001 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_HASH 0x002 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_CLASSID 0x004 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_LINK 0x008 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_PCNT 0x010 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_SELECTOR 0x020 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_ACTION 0x040 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_POLICE 0x080 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_INDEV 0x100 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf 4344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u) 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct tc_u32_sel *) u->cu_selector->d_data; 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u) 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!u->cu_selector) 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_selector = nl_data_alloc(NULL, sizeof(struct tc_u32_sel)); 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf return u32_selector(u); 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf 5644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy u32_policy[TCA_U32_MAX+1] = { 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_DIVISOR] = { .type = NLA_U32 }, 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_HASH] = { .type = NLA_U32 }, 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_CLASSID] = { .type = NLA_U32 }, 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_LINK] = { .type = NLA_U32 }, 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_INDEV] = { .type = NLA_STRING, 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf .maxlen = IFNAMSIZ }, 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) }, 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) }, 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf 6744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int u32_msg_parser(struct rtnl_cls *cls) 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 69ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[TCA_U32_MAX + 1]; 71ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf int err; 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf err = tca_parse(tb, TCA_U32_MAX, (struct rtnl_tca *) cls, u32_policy); 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_DIVISOR]) { 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_divisor = nla_get_u32(tb[TCA_U32_DIVISOR]); 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_DIVISOR; 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_SEL]) { 83eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]); 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!u->cu_selector) 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_nomem; 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_SELECTOR; 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_HASH]) { 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]); 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_HASH; 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_CLASSID]) { 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_classid = nla_get_u32(tb[TCA_U32_CLASSID]); 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_CLASSID; 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_LINK]) { 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_link = nla_get_u32(tb[TCA_U32_LINK]); 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_LINK; 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_ACT]) { 105eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf u->cu_act = nl_data_alloc_attr(tb[TCA_U32_ACT]); 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!u->cu_act) 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_nomem; 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_ACTION; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_POLICE]) { 112eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]); 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!u->cu_police) 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_nomem; 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_POLICE; 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_PCNT]) { 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_sel *sel; 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf int pcnt_size; 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!tb[TCA_U32_SEL]) { 1238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_MISSING_ATTR; 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf sel = u->cu_selector->d_data; 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf pcnt_size = sizeof(struct tc_u32_pcnt) + 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf (sel->nkeys * sizeof(uint64_t)); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nla_len(tb[TCA_U32_PCNT]) < pcnt_size) { 1318a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_INVAL; 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 135eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]); 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!u->cu_pcnt) 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_nomem; 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_PCNT; 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_U32_INDEV]) { 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_strlcpy(u->cu_indev, tb[TCA_U32_INDEV], IFNAMSIZ); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_INDEV; 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf 14844d362409d5469aed47d19e7908d19bd194493aThomas Graferrout_nomem: 1498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 15044d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf 15444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void u32_free_data(struct rtnl_cls *cls) 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 156ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(u->cu_selector); 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(u->cu_act); 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(u->cu_police); 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(u->cu_pcnt); 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf 16444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int u32_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src) 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 166ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *dst = rtnl_cls_data(_dst); 167ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *src = rtnl_cls_data(_src); 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 169ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (src->cu_selector && 170ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf !(dst->cu_selector = nl_data_clone(src->cu_selector))) 1718a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf 173ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (src->cu_act && !(dst->cu_act = nl_data_clone(src->cu_act))) 174ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return -NLE_NOMEM; 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf 176ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police))) 177ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return -NLE_NOMEM; 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf 179ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt))) 180ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return -NLE_NOMEM; 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf 185d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void u32_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p) 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 187ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[32]; 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_DIVISOR) 191d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " divisor %u", u->cu_divisor); 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (u->cu_mask & U32_ATTR_CLASSID) 193d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " target %s", 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_tc_handle2str(u->cu_classid, buf, sizeof(buf))); 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf 197d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel, 198d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf struct rtnl_cls *cls, struct rtnl_u32 *u) 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_key *key; 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sel->hmask || sel->hoff) { 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf /* I guess this will never be used since the kernel only 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf * exports the selector if no divisor is set but hash offset 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf * and hash mask make only sense in hash filters with divisor 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf * set */ 208d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " hash at %u & 0x%x", sel->hoff, sel->hmask); 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sel->flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) { 212d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " offset at %u", sel->off); 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sel->flags & TC_U32_VAROFFSET) 215d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " variable (at %u & 0x%x) >> %u", 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->offoff, ntohs(sel->offmask), sel->offshift); 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (sel->flags) { 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf int flags = sel->flags; 221d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " <"); 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf#define PRINT_FLAG(f) if (flags & TC_U32_##f) { \ 224d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf flags &= ~TC_U32_##f; nl_dump(p, #f "%s", flags ? "," : ""); } 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf PRINT_FLAG(TERMINAL); 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf PRINT_FLAG(OFFSET); 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf PRINT_FLAG(VAROFFSET); 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf PRINT_FLAG(EAT); 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef PRINT_FLAG 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf 232d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, ">"); 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i < sel->nkeys; i++) { 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i; 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf 239d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 240d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " match key at %s%u ", 241d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf key->offmask ? "nexthdr+" : "", key->off); 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (key->offmask) 244d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "[0x%u] ", key->offmask); 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf 246d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "& 0x%08x == 0x%08x", ntohl(key->mask), ntohl(key->val)); 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (p->dp_type == NL_DUMP_STATS && 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf (u->cu_mask & U32_ATTR_PCNT)) { 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_pcnt *pcnt = u->cu_pcnt->d_data; 251d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " successful %" PRIu64, pcnt->kcnts[i]); 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf 256d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void u32_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p) 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 258ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_sel *s; 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!(u->cu_mask & U32_ATTR_SELECTOR)) { 262d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "no-selector\n"); 263d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf return; 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf s = u->cu_selector->d_data; 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf 268d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "nkeys %u ", s->nkeys); 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_HASH) 271d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "ht key 0x%x hash 0x%u", 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash)); 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_LINK) 275d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "link %u ", u->cu_link); 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_INDEV) 278d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "indev %s ", u->cu_indev); 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf 280d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf print_selector(p, s, cls, u); 281d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf#if 0 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_ACTION 0x040 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define U32_ATTR_POLICE 0x080 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_data act; 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_data police; 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf#endif 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf 292d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void u32_dump_stats(struct rtnl_cls *cls, struct nl_dump_params *p) 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 294ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_PCNT) { 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_pcnt *pc = u->cu_pcnt->d_data; 298d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 299ff76549013c31082d303b3feef755bbd35e13ec6Denys Fedoryschenko nl_dump_line(p, " hit %8llu count %8llu\n", 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf pc->rhit, pc->rcnt); 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf 304ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafstatic int u32_get_opts(struct rtnl_cls *cls, struct nl_msg *msg) 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 306ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf 30844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_DIVISOR) 309ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor); 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_HASH) 312ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_U32(msg, TCA_U32_HASH, u->cu_hash); 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_CLASSID) 315ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_U32(msg, TCA_U32_CLASSID, u->cu_classid); 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_LINK) 318ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_U32(msg, TCA_U32_LINK, u->cu_link); 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_SELECTOR) 321ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector); 32244d362409d5469aed47d19e7908d19bd194493aThomas Graf 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_ACTION) 324ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_DATA(msg, TCA_U32_ACT, u->cu_act); 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_POLICE) 327ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_DATA(msg, TCA_U32_POLICE, u->cu_police); 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (u->cu_mask & U32_ATTR_INDEV) 330ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf NLA_PUT_STRING(msg, TCA_U32_INDEV, u->cu_indev); 33144d362409d5469aed47d19e7908d19bd194493aThomas Graf 332ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return 0; 333ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 334ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafnla_put_failure: 335ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return -NLE_NOMEM; 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Modifications 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf 34344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash, 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf int nodeid) 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t handle = (htid << 20) | (hash << 12) | nodeid; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf tca_set_handle((struct rtnl_tca *) cls, handle ); 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf 35144d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid) 35244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 353ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 35444d362409d5469aed47d19e7908d19bd194493aThomas Graf 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_classid = classid; 35644d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_CLASSID; 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Selector Modifications 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf 36844d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_set_flags(struct rtnl_cls *cls, int flags) 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_sel *sel; 371ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf sel = u32_selector_alloc(u); 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!sel) 3758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->flags |= flags; 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_SELECTOR; 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf 38044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Append new 32-bit key to the selector 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cls classifier to be modifier 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg val value to be matched (network byte-order) 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg mask mask to be applied before matching (network byte-order) 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg off offset, in bytes, to start matching 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg offmask offset mask 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf * General selectors define the pattern, mask and offset the pattern will be 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf * matched to the packet contents. Using the general selectors you can match 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf * virtually any single bit in the IP (or upper layer) header. 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf*/ 39744d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf int off, int offmask) 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_u32_sel *sel; 401ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_u32 *u = rtnl_cls_data(cls); 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 40344d362409d5469aed47d19e7908d19bd194493aThomas Graf 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf sel = u32_selector_alloc(u); 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!sel) 4068a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf 40844d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key)); 40944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 41144d362409d5469aed47d19e7908d19bd194493aThomas Graf 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf /* the selector might have been moved by realloc */ 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf sel = u32_selector(u); 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->keys[sel->nkeys].mask = mask; 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->keys[sel->nkeys].val = val & mask; 41744d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->keys[sel->nkeys].off = off; 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->keys[sel->nkeys].offmask = offmask; 41944d362409d5469aed47d19e7908d19bd194493aThomas Graf sel->nkeys++; 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf u->cu_mask |= U32_ATTR_SELECTOR; 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf 42544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask, 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf int off, int offmask) 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf int shift = 24 - 8 * (off & 3); 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf htonl((uint32_t)mask << shift), 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf off & ~3, offmask); 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Append new selector key to match a 16-bit number 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cls classifier to be modified 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg val value to be matched (host byte-order) 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg mask mask to be applied before matching (host byte-order) 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg off offset, in bytes, to start matching 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg offmask offset mask 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf*/ 44444d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask, 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf int off, int offmask) 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf int shift = ((off & 3) == 0 ? 16 : 0); 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (off % 2) 4498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf 45144d362409d5469aed47d19e7908d19bd194493aThomas Graf return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift), 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf htonl((uint32_t)mask << shift), 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf off & ~3, offmask); 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 45544d362409d5469aed47d19e7908d19bd194493aThomas Graf 45644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Append new selector key to match a 32-bit number 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cls classifier to be modified 46044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg val value to be matched (host byte-order) 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg mask mask to be applied before matching (host byte-order) 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg off offset, in bytes, to start matching 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg offmask offset mask 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf*/ 46544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask, 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf int off, int offmask) 46744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 46844d362409d5469aed47d19e7908d19bd194493aThomas Graf return rtnl_u32_add_key(cls, htonl(val), htonl(mask), 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf off & ~3, offmask); 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf 47244d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, struct in_addr *addr, 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf uint8_t bitmask, int off, int offmask) 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t mask = 0xFFFFFFFF << (32 - bitmask); 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask); 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf 47944d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, struct in6_addr *addr, 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint8_t bitmask, int off, int offmask) 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf int i, err; 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 1; i <= 4; i++) { 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (32 * i - bitmask <= 0) { 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf 0xFFFFFFFF, off+4*(i-1), offmask)) < 0) 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 49044d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (32 * i - bitmask < 32) { 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t mask = 0xFFFFFFFF << (32 * i - bitmask); 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1], 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf htonl(mask), off+4*(i-1), offmask)) < 0) 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 49644d362409d5469aed47d19e7908d19bd194493aThomas Graf /* otherwise, if (32*i - bitmask >= 32) no key is generated */ 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 49844d362409d5469aed47d19e7908d19bd194493aThomas Graf 49944d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf 50444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct rtnl_cls_ops u32_ops = { 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_kind = "u32", 506ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf .co_size = sizeof(struct rtnl_u32), 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = u32_msg_parser, 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_free_data = u32_free_data, 50944d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_clone = u32_clone, 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_get_opts = u32_get_opts, 511d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .co_dump = { 512d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = u32_dump_line, 513d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = u32_dump_details, 514d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_STATS] = u32_dump_stats, 515d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf 51844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init u32_init(void) 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_cls_register(&u32_ops); 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf 52344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit u32_exit(void) 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 52544d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_cls_unregister(&u32_ops); 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 52744d362409d5469aed47d19e7908d19bd194493aThomas Graf 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 529