|
@@ -11,9 +11,7 @@
|
|
|
|
|
|
struct ila_xlat_params {
|
|
|
struct ila_params ip;
|
|
|
- struct ila_identifier identifier;
|
|
|
int ifindex;
|
|
|
- unsigned int dir;
|
|
|
};
|
|
|
|
|
|
struct ila_map {
|
|
@@ -66,35 +64,29 @@ static __always_inline void __ila_hash_secret_init(void)
|
|
|
net_get_random_once(&hashrnd, sizeof(hashrnd));
|
|
|
}
|
|
|
|
|
|
-static inline u32 ila_identifier_hash(struct ila_identifier ident)
|
|
|
+static inline u32 ila_locator_hash(struct ila_locator loc)
|
|
|
{
|
|
|
- u32 *v = (u32 *)ident.v32;
|
|
|
+ u32 *v = (u32 *)loc.v32;
|
|
|
|
|
|
return jhash_2words(v[0], v[1], hashrnd);
|
|
|
}
|
|
|
|
|
|
static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
|
|
|
- struct ila_identifier ident)
|
|
|
+ struct ila_locator loc)
|
|
|
{
|
|
|
- return &ilan->locks[ila_identifier_hash(ident) & ilan->locks_mask];
|
|
|
+ return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
|
|
|
}
|
|
|
|
|
|
static inline int ila_cmp_wildcards(struct ila_map *ila,
|
|
|
- struct ila_addr *iaddr, int ifindex,
|
|
|
- unsigned int dir)
|
|
|
+ struct ila_addr *iaddr, int ifindex)
|
|
|
{
|
|
|
- return (ila->xp.ip.locator_match.v64 &&
|
|
|
- ila->xp.ip.locator_match.v64 != iaddr->loc.v64) ||
|
|
|
- (ila->xp.ifindex && ila->xp.ifindex != ifindex) ||
|
|
|
- !(ila->xp.dir & dir);
|
|
|
+ return (ila->xp.ifindex && ila->xp.ifindex != ifindex);
|
|
|
}
|
|
|
|
|
|
static inline int ila_cmp_params(struct ila_map *ila,
|
|
|
struct ila_xlat_params *xp)
|
|
|
{
|
|
|
- return (ila->xp.ip.locator_match.v64 != xp->ip.locator_match.v64) ||
|
|
|
- (ila->xp.ifindex != xp->ifindex) ||
|
|
|
- (ila->xp.dir != xp->dir);
|
|
|
+ return (ila->xp.ifindex != xp->ifindex);
|
|
|
}
|
|
|
|
|
|
static int ila_cmpfn(struct rhashtable_compare_arg *arg,
|
|
@@ -102,16 +94,13 @@ static int ila_cmpfn(struct rhashtable_compare_arg *arg,
|
|
|
{
|
|
|
const struct ila_map *ila = obj;
|
|
|
|
|
|
- return (ila->xp.identifier.v64 != *(__be64 *)arg->key);
|
|
|
+ return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key);
|
|
|
}
|
|
|
|
|
|
static inline int ila_order(struct ila_map *ila)
|
|
|
{
|
|
|
int score = 0;
|
|
|
|
|
|
- if (ila->xp.ip.locator_match.v64)
|
|
|
- score += 1 << 0;
|
|
|
-
|
|
|
if (ila->xp.ifindex)
|
|
|
score += 1 << 1;
|
|
|
|
|
@@ -121,7 +110,7 @@ static inline int ila_order(struct ila_map *ila)
|
|
|
static const struct rhashtable_params rht_params = {
|
|
|
.nelem_hint = 1024,
|
|
|
.head_offset = offsetof(struct ila_map, node),
|
|
|
- .key_offset = offsetof(struct ila_map, xp.identifier),
|
|
|
+ .key_offset = offsetof(struct ila_map, xp.ip.locator_match),
|
|
|
.key_len = sizeof(u64), /* identifier */
|
|
|
.max_size = 1048576,
|
|
|
.min_size = 256,
|
|
@@ -140,11 +129,9 @@ static struct genl_family ila_nl_family = {
|
|
|
};
|
|
|
|
|
|
static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
|
|
|
- [ILA_ATTR_IDENTIFIER] = { .type = NLA_U64, },
|
|
|
[ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
|
|
|
[ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
|
|
|
[ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
|
|
|
- [ILA_ATTR_DIR] = { .type = NLA_U32, },
|
|
|
};
|
|
|
|
|
|
static int parse_nl_config(struct genl_info *info,
|
|
@@ -152,10 +139,6 @@ static int parse_nl_config(struct genl_info *info,
|
|
|
{
|
|
|
memset(xp, 0, sizeof(*xp));
|
|
|
|
|
|
- if (info->attrs[ILA_ATTR_IDENTIFIER])
|
|
|
- xp->identifier.v64 = (__force __be64)nla_get_u64(
|
|
|
- info->attrs[ILA_ATTR_IDENTIFIER]);
|
|
|
-
|
|
|
if (info->attrs[ILA_ATTR_LOCATOR])
|
|
|
xp->ip.locator.v64 = (__force __be64)nla_get_u64(
|
|
|
info->attrs[ILA_ATTR_LOCATOR]);
|
|
@@ -167,24 +150,20 @@ static int parse_nl_config(struct genl_info *info,
|
|
|
if (info->attrs[ILA_ATTR_IFINDEX])
|
|
|
xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
|
|
|
|
|
|
- if (info->attrs[ILA_ATTR_DIR])
|
|
|
- xp->dir = nla_get_u32(info->attrs[ILA_ATTR_DIR]);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/* Must be called with rcu readlock */
|
|
|
static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
|
|
|
int ifindex,
|
|
|
- unsigned int dir,
|
|
|
struct ila_net *ilan)
|
|
|
{
|
|
|
struct ila_map *ila;
|
|
|
|
|
|
- ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->ident,
|
|
|
+ ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
|
|
|
rht_params);
|
|
|
while (ila) {
|
|
|
- if (!ila_cmp_wildcards(ila, iaddr, ifindex, dir))
|
|
|
+ if (!ila_cmp_wildcards(ila, iaddr, ifindex))
|
|
|
return ila;
|
|
|
ila = rcu_access_pointer(ila->next);
|
|
|
}
|
|
@@ -198,7 +177,8 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
|
|
|
{
|
|
|
struct ila_map *ila;
|
|
|
|
|
|
- ila = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
|
|
|
+ ila = rhashtable_lookup_fast(&ilan->rhash_table,
|
|
|
+ &xp->ip.locator_match,
|
|
|
rht_params);
|
|
|
while (ila) {
|
|
|
if (!ila_cmp_params(ila, xp))
|
|
@@ -226,14 +206,14 @@ static void ila_free_cb(void *ptr, void *arg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int ila_xlat_addr(struct sk_buff *skb, int dir);
|
|
|
+static int ila_xlat_addr(struct sk_buff *skb);
|
|
|
|
|
|
static unsigned int
|
|
|
ila_nf_input(void *priv,
|
|
|
struct sk_buff *skb,
|
|
|
const struct nf_hook_state *state)
|
|
|
{
|
|
|
- ila_xlat_addr(skb, ILA_DIR_IN);
|
|
|
+ ila_xlat_addr(skb);
|
|
|
return NF_ACCEPT;
|
|
|
}
|
|
|
|
|
@@ -250,7 +230,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
|
|
|
{
|
|
|
struct ila_net *ilan = net_generic(net, ila_net_id);
|
|
|
struct ila_map *ila, *head;
|
|
|
- spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
|
|
|
+ spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
|
|
|
int err = 0, order;
|
|
|
|
|
|
if (!ilan->hooks_registered) {
|
|
@@ -271,20 +251,19 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
|
|
|
|
|
|
ila->xp = *xp;
|
|
|
|
|
|
- if (xp->ip.locator_match.v64) {
|
|
|
- /* Precompute checksum difference for translation since we
|
|
|
- * know both the old identifier and the new one.
|
|
|
- */
|
|
|
- ila->xp.ip.csum_diff = compute_csum_diff8(
|
|
|
- (__be32 *)&xp->ip.locator_match,
|
|
|
- (__be32 *)&xp->ip.locator);
|
|
|
- }
|
|
|
+ /* Precompute checksum difference for translation since we
|
|
|
+ * know both the old identifier and the new one.
|
|
|
+ */
|
|
|
+ ila->xp.ip.csum_diff = compute_csum_diff8(
|
|
|
+ (__be32 *)&xp->ip.locator_match,
|
|
|
+ (__be32 *)&xp->ip.locator);
|
|
|
|
|
|
order = ila_order(ila);
|
|
|
|
|
|
spin_lock(lock);
|
|
|
|
|
|
- head = rhashtable_lookup_fast(&ilan->rhash_table, &xp->identifier,
|
|
|
+ head = rhashtable_lookup_fast(&ilan->rhash_table,
|
|
|
+ &xp->ip.locator_match,
|
|
|
rht_params);
|
|
|
if (!head) {
|
|
|
/* New entry for the rhash_table */
|
|
@@ -335,13 +314,13 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
|
|
|
{
|
|
|
struct ila_net *ilan = net_generic(net, ila_net_id);
|
|
|
struct ila_map *ila, *head, *prev;
|
|
|
- spinlock_t *lock = ila_get_lock(ilan, xp->identifier);
|
|
|
+ spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
|
|
|
int err = -ENOENT;
|
|
|
|
|
|
spin_lock(lock);
|
|
|
|
|
|
head = rhashtable_lookup_fast(&ilan->rhash_table,
|
|
|
- &xp->identifier, rht_params);
|
|
|
+ &xp->ip.locator_match, rht_params);
|
|
|
ila = head;
|
|
|
|
|
|
prev = NULL;
|
|
@@ -423,17 +402,13 @@ static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
|
|
static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
|
|
|
{
|
|
|
- if (nla_put_u64_64bit(msg, ILA_ATTR_IDENTIFIER,
|
|
|
- (__force u64)ila->xp.identifier.v64,
|
|
|
- ILA_ATTR_PAD) ||
|
|
|
- nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
|
|
|
+ if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
|
|
|
(__force u64)ila->xp.ip.locator.v64,
|
|
|
ILA_ATTR_PAD) ||
|
|
|
nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH,
|
|
|
(__force u64)ila->xp.ip.locator_match.v64,
|
|
|
ILA_ATTR_PAD) ||
|
|
|
- nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) ||
|
|
|
- nla_put_u32(msg, ILA_ATTR_DIR, ila->xp.dir))
|
|
|
+ nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex))
|
|
|
return -1;
|
|
|
|
|
|
return 0;
|
|
@@ -622,22 +597,24 @@ static struct pernet_operations ila_net_ops = {
|
|
|
.size = sizeof(struct ila_net),
|
|
|
};
|
|
|
|
|
|
-static int ila_xlat_addr(struct sk_buff *skb, int dir)
|
|
|
+static int ila_xlat_addr(struct sk_buff *skb)
|
|
|
{
|
|
|
struct ila_map *ila;
|
|
|
struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
|
|
struct net *net = dev_net(skb->dev);
|
|
|
struct ila_net *ilan = net_generic(net, ila_net_id);
|
|
|
struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
|
|
|
- size_t nhoff;
|
|
|
|
|
|
/* Assumes skb contains a valid IPv6 header that is pulled */
|
|
|
|
|
|
- nhoff = sizeof(struct ipv6hdr);
|
|
|
+ if (!ila_addr_is_ila(iaddr)) {
|
|
|
+ /* Type indicates this is not an ILA address */
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
|
|
- ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, dir, ilan);
|
|
|
+ ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan);
|
|
|
if (ila)
|
|
|
ila_update_ipv6_locator(skb, &ila->xp.ip);
|
|
|
|
|
@@ -646,18 +623,6 @@ static int ila_xlat_addr(struct sk_buff *skb, int dir)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int ila_xlat_incoming(struct sk_buff *skb)
|
|
|
-{
|
|
|
- return ila_xlat_addr(skb, ILA_DIR_IN);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(ila_xlat_incoming);
|
|
|
-
|
|
|
-int ila_xlat_outgoing(struct sk_buff *skb)
|
|
|
-{
|
|
|
- return ila_xlat_addr(skb, ILA_DIR_OUT);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(ila_xlat_outgoing);
|
|
|
-
|
|
|
int ila_xlat_init(void)
|
|
|
{
|
|
|
int ret;
|