Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'ila-make-identifier-format-optional-and-other-fixes'

Tom Herbert says:

====================
ila: make identifier format optional and other fixes

The identifier type and checksum neutral mapping bits are optional
in identifier formats. This patch set fixes the implementation to
make them optional and configurable.

Specific items:

- Clean up checksum diff code in ILA
- Add checksum neutral mapping auto so that checksum neutral
mapping can be configured without requiring use of the C-bit
- Add identifier type configuration and allow identifier
type to be configured so that the identifier type field does
not need to be present
- Added ILA documention: ila.txt

I have fixes for ILA in iproute2 that will be poseted separately.

Tested: Ran netperf TCP_RR on various combinations of checksum
mode and the two supported identifier types.

v2:
- Add proper sign off
- In ILA LWT, only check prefix length includes identifier type
if identifier type is enabled (ILA_ATYPE_USE_FORMAT).
- Add a hook type so that it can be specified whether ILA
translation is done on input or output route funciton in
LWT.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+477 -90
+285
Documentation/networking/ila.txt
··· 1 + Identifier Locator Addressing (ILA) 2 + 3 + 4 + Introduction 5 + ============ 6 + 7 + Identifier-locator addressing (ILA) is a technique used with IPv6 that 8 + differentiates between location and identity of a network node. Part of an 9 + address expresses the immutable identity of the node, and another part 10 + indicates the location of the node which can be dynamic. Identifier-locator 11 + addressing can be used to efficiently implement overlay networks for 12 + network virtualization as well as solutions for use cases in mobility. 13 + 14 + ILA can be thought of as means to implement an overlay network without 15 + encapsulation. This is accomplished by performing network address 16 + translation on destination addresses as a packet traverses a network. To 17 + the network, an ILA translated packet appears to be no different than any 18 + other IPv6 packet. For instance, if the transport protocol is TCP then an 19 + ILA translated packet looks like just another TCP/IPv6 packet. The 20 + advantage of this is that ILA is transparent to the network so that 21 + optimizations in the network, such as ECMP, RSS, GRO, GSO, etc., just work. 22 + 23 + The ILA protocol is described in Internet-Draft draft-herbert-intarea-ila. 24 + 25 + 26 + ILA terminology 27 + =============== 28 + 29 + - Identifier A number that identifies an addressable node in the network 30 + independent of its location. ILA identifiers are sixty-four 31 + bit values. 32 + 33 + - Locator A network prefix that routes to a physical host. Locators 34 + provide the topological location of an addressed node. ILA 35 + locators are sixty-four bit prefixes. 36 + 37 + - ILA mapping 38 + A mapping of an ILA identifier to a locator (or to a 39 + locator and meta data). An ILA domain maintains a database 40 + that contains mappings for all destinations in the domain. 41 + 42 + - SIR address 43 + An IPv6 address composed of a SIR prefix (upper sixty- 44 + four bits) and an identifier (lower sixty-four bits). 45 + SIR addresses are visible to applications and provide a 46 + means for them to address nodes independent of their 47 + location. 48 + 49 + - ILA address 50 + An IPv6 address composed of a locator (upper sixty-four 51 + bits) and an identifier (low order sixty-four bits). ILA 52 + addresses are never visible to an application. 53 + 54 + - ILA host An end host that is capable of performing ILA translations 55 + on transmit or receive. 56 + 57 + - ILA router A network node that performs ILA translation and forwarding 58 + of translated packets. 59 + 60 + - ILA forwarding cache 61 + A type of ILA router that only maintains a working set 62 + cache of mappings. 63 + 64 + - ILA node A network node capable of performing ILA translations. This 65 + can be an ILA router, ILA forwarding cache, or ILA host. 66 + 67 + 68 + Operation 69 + ========= 70 + 71 + There are two fundamental operations with ILA: 72 + 73 + - Translate a SIR address to an ILA address. This is performed on ingress 74 + to an ILA overlay. 75 + 76 + - Translate an ILA address to a SIR address. This is performed on egress 77 + from the ILA overlay. 78 + 79 + ILA can be deployed either on end hosts or intermediate devices in the 80 + network; these are provided by "ILA hosts" and "ILA routers" respectively. 81 + Configuration and datapath for these two points of deployment is somewhat 82 + different. 83 + 84 + The diagram below illustrates the flow of packets through ILA as well 85 + as showing ILA hosts and routers. 86 + 87 + +--------+ +--------+ 88 + | Host A +-+ +--->| Host B | 89 + | | | (2) ILA (') | | 90 + +--------+ | ...addressed.... ( ) +--------+ 91 + V +---+--+ . packet . +---+--+ (_) 92 + (1) SIR | | ILA |----->-------->---->| ILA | | (3) SIR 93 + addressed +->|router| . . |router|->-+ addressed 94 + packet +---+--+ . IPv6 . +---+--+ packet 95 + / . Network . 96 + / . . +--+-++--------+ 97 + +--------+ / . . |ILA || Host | 98 + | Host +--+ . .- -|host|| | 99 + | | . . +--+-++--------+ 100 + +--------+ ................ 101 + 102 + 103 + Transport checksum handling 104 + =========================== 105 + 106 + When an address is translated by ILA, an encapsulated transport checksum 107 + that includes the translated address in a pseudo header may be rendered 108 + incorrect on the wire. This is a problem for intermediate devices, 109 + including checksum offload in NICs, that process the checksum. There are 110 + three options to deal with this: 111 + 112 + - no action Allow the checksum to be incorrect on the wire. Before 113 + a receiver verifies a checksum the ILA to SIR address 114 + translation must be done. 115 + 116 + - adjust transport checksum 117 + When ILA translation is performed the packet is parsed 118 + and if a transport layer checksum is found then it is 119 + adjusted to reflect the correct checksum per the 120 + translated address. 121 + 122 + - checksum neutral mapping 123 + When an address is translated the difference can be offset 124 + elsewhere in a part of the packet that is covered by the 125 + the checksum. The low order sixteen bits of the identifier 126 + are used. This method is preferred since it doesn't require 127 + parsing a packet beyond the IP header and in most cases the 128 + adjustment can be precomputed and saved with the mapping. 129 + 130 + Note that the checksum neutral adjustment affects the low order sixteen 131 + bits of the identifier. When ILA to SIR address translation is done on 132 + egress the low order bits are restored to the original value which 133 + restores the identifier as it was originally sent. 134 + 135 + 136 + Identifier types 137 + ================ 138 + 139 + ILA defines different types of identifiers for different use cases. 140 + 141 + The defined types are: 142 + 143 + 0: interface identifier 144 + 145 + 1: locally unique identifier 146 + 147 + 2: virtual networking identifier for IPv4 address 148 + 149 + 3: virtual networking identifier for IPv6 unicast address 150 + 151 + 4: virtual networking identifier for IPv6 multicast address 152 + 153 + 5: non-local address identifier 154 + 155 + In the current implementation of kernel ILA only locally unique identifiers 156 + (LUID) are supported. LUID allows for a generic, unformatted 64 bit 157 + identifier. 158 + 159 + 160 + Identifier formats 161 + ================== 162 + 163 + Kernel ILA supports two optional fields in an identifier for formatting: 164 + "C-bit" and "identifier type". The presence of these fields is determined 165 + by configuration as demonstrated below. 166 + 167 + If the identifier type is present it occupies the three highest order 168 + bits of an identifier. The possible values are given in the above list. 169 + 170 + If the C-bit is present, this is used as an indication that checksum 171 + neutral mapping has been done. The C-bit can only be set in an 172 + ILA address, never a SIR address. 173 + 174 + In the simplest format the identifier types, C-bit, and checksum 175 + adjustment value are not present so an identifier is considered an 176 + unstructured sixty-four bit value. 177 + 178 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179 + | Identifier | 180 + + + 181 + | | 182 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 183 + 184 + The checksum neutral adjustment may be configured to always be 185 + present using neutral-map-auto. In this case there is no C-bit, but the 186 + checksum adjustment is in the low order 16 bits. The identifier is 187 + still sixty-four bits. 188 + 189 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 190 + | Identifier | 191 + | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 192 + | | Checksum-neutral adjustment | 193 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 194 + 195 + The C-bit may used to explicitly indicate that checksum neutral 196 + mapping has been applied to an ILA address. The format is: 197 + 198 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 199 + | |C| Identifier | 200 + | +-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 201 + | | Checksum-neutral adjustment | 202 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 203 + 204 + The identifier type field may be present to indicate the identifier 205 + type. If it is not present then the type is inferred based on mapping 206 + configuration. The checksum neutral adjustment may automatically 207 + used with the identifier type as illustrated below. 208 + 209 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210 + | Type| Identifier | 211 + +-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212 + | | Checksum-neutral adjustment | 213 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214 + 215 + If the identifier type and the C-bit can be present simultaneously so 216 + the identifier format would be: 217 + 218 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 219 + | Type|C| Identifier | 220 + +-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 221 + | | Checksum-neutral adjustment | 222 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 223 + 224 + 225 + Configuration 226 + ============= 227 + 228 + There are two methods to configure ILA mappings. One is by using LWT routes 229 + and the other is ila_xlat (called from NFHOOK PREROUTING hook). ila_xlat 230 + is intended to be used in the receive path for ILA hosts . 231 + 232 + An ILA router has also been implemented in XDP. Description of that is 233 + outside the scope of this document. 234 + 235 + The usage of for ILA LWT routes is: 236 + 237 + ip route add DEST/128 encap ila LOC csum-mode MODE ident-type TYPE via ADDR 238 + 239 + Destination (DEST) can either be a SIR address (for an ILA host or ingress 240 + ILA router) or an ILA address (egress ILA router). LOC is the sixty-four 241 + bit locator (with format W:X:Y:Z) that overwrites the upper sixty-four 242 + bits of the destination address. Checksum MODE is one of "no-action", 243 + "adj-transport", "neutral-map", and "neutral-map-auto". If neutral-map is 244 + set then the C-bit will be present. Identifier TYPE one of "luid" or 245 + "use-format." In the case of use-format, the identifier type field is 246 + present and the effective type is taken from that. 247 + 248 + The usage of ila_xlat is: 249 + 250 + ip ila add loc_match MATCH loc LOC csum-mode MODE ident-type TYPE 251 + 252 + MATCH indicates the incoming locator that must be matched to apply 253 + a the translaiton. LOC is the locator that overwrites the upper 254 + sixty-four bits of the destination address. MODE and TYPE have the 255 + same meanings as described above. 256 + 257 + 258 + Some examples 259 + ============= 260 + 261 + # Configure an ILA route that uses checksum neutral mapping as well 262 + # as type field. Note that the type field is set in the SIR address 263 + # (the 2000 implies type is 1 which is LUID). 264 + ip route add 3333:0:0:1:2000:0:1:87/128 encap ila 2001:0:87:0 \ 265 + csum-mode neutral-map ident-type use-format 266 + 267 + # Configure an ILA LWT route that uses auto checksum neutral mapping 268 + # (no C-bit) and configure identifier type to be LUID so that the 269 + # identifier type field will not be present. 270 + ip route add 3333:0:0:1:2000:0:2:87/128 encap ila 2001:0:87:1 \ 271 + csum-mode neutral-map-auto ident-type luid 272 + 273 + ila_xlat configuration 274 + 275 + # Configure an ILA to SIR mapping that matches a locator and overwrites 276 + # it with a SIR address (3333:0:0:1 in this example). The C-bit and 277 + # identifier field are used. 278 + ip ila add loc_match 2001:0:119:0 loc 3333:0:0:1 \ 279 + csum-mode neutral-map-auto ident-type use-format 280 + 281 + # Configure an ILA to SIR mapping where checksum neutral is automatically 282 + # set without the C-bit and the identifier type is configured to be LUID 283 + # so that the identifier type field is not present. 284 + ip ila add loc_match 2001:0:119:0 loc 3333:0:0:1 \ 285 + csum-mode neutral-map-auto ident-type use-format
+21
include/uapi/linux/ila.h
··· 17 17 ILA_ATTR_DIR, /* u32 */ 18 18 ILA_ATTR_PAD, 19 19 ILA_ATTR_CSUM_MODE, /* u8 */ 20 + ILA_ATTR_IDENT_TYPE, /* u8 */ 21 + ILA_ATTR_HOOK_TYPE, /* u8 */ 20 22 21 23 __ILA_ATTR_MAX, 22 24 }; ··· 43 41 ILA_CSUM_ADJUST_TRANSPORT, 44 42 ILA_CSUM_NEUTRAL_MAP, 45 43 ILA_CSUM_NO_ACTION, 44 + ILA_CSUM_NEUTRAL_MAP_AUTO, 45 + }; 46 + 47 + enum { 48 + ILA_ATYPE_IID = 0, 49 + ILA_ATYPE_LUID, 50 + ILA_ATYPE_VIRT_V4, 51 + ILA_ATYPE_VIRT_UNI_V6, 52 + ILA_ATYPE_VIRT_MULTI_V6, 53 + ILA_ATYPE_NONLOCAL_ADDR, 54 + ILA_ATYPE_RSVD_1, 55 + ILA_ATYPE_RSVD_2, 56 + 57 + ILA_ATYPE_USE_FORMAT = 32, /* Get type from type field in identifier */ 58 + }; 59 + 60 + enum { 61 + ILA_HOOK_ROUTE_OUTPUT, 62 + ILA_HOOK_ROUTE_INPUT, 46 63 }; 47 64 48 65 #endif /* _UAPI_LINUX_ILA_H */
+1 -11
net/ipv6/ila/ila.h
··· 55 55 }; 56 56 }; 57 57 58 - enum { 59 - ILA_ATYPE_IID = 0, 60 - ILA_ATYPE_LUID, 61 - ILA_ATYPE_VIRT_V4, 62 - ILA_ATYPE_VIRT_UNI_V6, 63 - ILA_ATYPE_VIRT_MULTI_V6, 64 - ILA_ATYPE_RSVD_1, 65 - ILA_ATYPE_RSVD_2, 66 - ILA_ATYPE_RSVD_3, 67 - }; 68 - 69 58 #define CSUM_NEUTRAL_FLAG htonl(0x10000000) 70 59 71 60 struct ila_addr { ··· 82 93 struct ila_locator locator_match; 83 94 __wsum csum_diff; 84 95 u8 csum_mode; 96 + u8 ident_type; 85 97 }; 86 98 87 99 static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to)
+57 -47
net/ipv6/ila/ila_common.c
··· 13 13 #include <uapi/linux/ila.h> 14 14 #include "ila.h" 15 15 16 - static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) 16 + void ila_init_saved_csum(struct ila_params *p) 17 17 { 18 - struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); 18 + if (!p->locator_match.v64) 19 + return; 19 20 21 + p->csum_diff = compute_csum_diff8( 22 + (__be32 *)&p->locator, 23 + (__be32 *)&p->locator_match); 24 + } 25 + 26 + static __wsum get_csum_diff_iaddr(struct ila_addr *iaddr, struct ila_params *p) 27 + { 20 28 if (p->locator_match.v64) 21 29 return p->csum_diff; 22 30 else 23 - return compute_csum_diff8((__be32 *)&iaddr->loc, 24 - (__be32 *)&p->locator); 31 + return compute_csum_diff8((__be32 *)&p->locator, 32 + (__be32 *)&iaddr->loc); 25 33 } 26 34 27 - static void ila_csum_do_neutral(struct ila_addr *iaddr, 28 - struct ila_params *p) 35 + static __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p) 36 + { 37 + return get_csum_diff_iaddr(ila_a2i(&ip6h->daddr), p); 38 + } 39 + 40 + static void ila_csum_do_neutral_fmt(struct ila_addr *iaddr, 41 + struct ila_params *p) 29 42 { 30 43 __sum16 *adjust = (__force __sum16 *)&iaddr->ident.v16[3]; 31 44 __wsum diff, fval; 32 45 33 - /* Check if checksum adjust value has been cached */ 34 - if (p->locator_match.v64) { 35 - diff = p->csum_diff; 36 - } else { 37 - diff = compute_csum_diff8((__be32 *)&p->locator, 38 - (__be32 *)iaddr); 39 - } 46 + diff = get_csum_diff_iaddr(iaddr, p); 40 47 41 48 fval = (__force __wsum)(ila_csum_neutral_set(iaddr->ident) ? 42 49 CSUM_NEUTRAL_FLAG : ~CSUM_NEUTRAL_FLAG); ··· 60 53 iaddr->ident.csum_neutral ^= 1; 61 54 } 62 55 56 + static void ila_csum_do_neutral_nofmt(struct ila_addr *iaddr, 57 + struct ila_params *p) 58 + { 59 + __sum16 *adjust = (__force __sum16 *)&iaddr->ident.v16[3]; 60 + __wsum diff; 61 + 62 + diff = get_csum_diff_iaddr(iaddr, p); 63 + 64 + *adjust = ~csum_fold(csum_add(diff, csum_unfold(*adjust))); 65 + } 66 + 63 67 static void ila_csum_adjust_transport(struct sk_buff *skb, 64 68 struct ila_params *p) 65 69 { 66 - __wsum diff; 67 - struct ipv6hdr *ip6h = ipv6_hdr(skb); 68 - struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); 69 70 size_t nhoff = sizeof(struct ipv6hdr); 71 + struct ipv6hdr *ip6h = ipv6_hdr(skb); 72 + __wsum diff; 70 73 71 74 switch (ip6h->nexthdr) { 72 75 case NEXTHDR_TCP: ··· 115 98 } 116 99 break; 117 100 } 118 - 119 - /* Now change destination address */ 120 - iaddr->loc = p->locator; 121 101 } 122 102 123 103 void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p, 124 - bool set_csum_neutral) 104 + bool sir2ila) 125 105 { 126 106 struct ipv6hdr *ip6h = ipv6_hdr(skb); 127 107 struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); 128 108 129 - /* First deal with the transport checksum */ 130 - if (ila_csum_neutral_set(iaddr->ident)) { 131 - /* C-bit is set in the locator indicating that this 132 - * is a locator being translated to a SIR address. 133 - * Perform (receiver) checksum-neutral translation. 134 - */ 135 - if (!set_csum_neutral) 136 - ila_csum_do_neutral(iaddr, p); 137 - } else { 138 - switch (p->csum_mode) { 139 - case ILA_CSUM_ADJUST_TRANSPORT: 140 - ila_csum_adjust_transport(skb, p); 141 - break; 142 - case ILA_CSUM_NEUTRAL_MAP: 143 - ila_csum_do_neutral(iaddr, p); 144 - break; 145 - case ILA_CSUM_NO_ACTION: 109 + switch (p->csum_mode) { 110 + case ILA_CSUM_ADJUST_TRANSPORT: 111 + ila_csum_adjust_transport(skb, p); 112 + break; 113 + case ILA_CSUM_NEUTRAL_MAP: 114 + if (sir2ila) { 115 + if (WARN_ON(ila_csum_neutral_set(iaddr->ident))) { 116 + /* Checksum flag should never be 117 + * set in a formatted SIR address. 118 + */ 119 + break; 120 + } 121 + } else if (!ila_csum_neutral_set(iaddr->ident)) { 122 + /* ILA to SIR translation and C-bit isn't 123 + * set so we're good. 124 + */ 146 125 break; 147 126 } 127 + ila_csum_do_neutral_fmt(iaddr, p); 128 + break; 129 + case ILA_CSUM_NEUTRAL_MAP_AUTO: 130 + ila_csum_do_neutral_nofmt(iaddr, p); 131 + break; 132 + case ILA_CSUM_NO_ACTION: 133 + break; 148 134 } 149 135 150 136 /* Now change destination address */ 151 137 iaddr->loc = p->locator; 152 - } 153 - 154 - void ila_init_saved_csum(struct ila_params *p) 155 - { 156 - if (!p->locator_match.v64) 157 - return; 158 - 159 - p->csum_diff = compute_csum_diff8( 160 - (__be32 *)&p->locator, 161 - (__be32 *)&p->locator_match); 162 138 } 163 139 164 140 static int __init ila_init(void)
+95 -24
net/ipv6/ila/ila_lwt.c
··· 20 20 struct ila_params p; 21 21 struct dst_cache dst_cache; 22 22 u32 connected : 1; 23 + u32 lwt_output : 1; 23 24 }; 24 25 25 26 static inline struct ila_lwt *ila_lwt_lwtunnel( ··· 46 45 if (skb->protocol != htons(ETH_P_IPV6)) 47 46 goto drop; 48 47 49 - ila_update_ipv6_locator(skb, ila_params_lwtunnel(orig_dst->lwtstate), 50 - true); 48 + if (ilwt->lwt_output) 49 + ila_update_ipv6_locator(skb, 50 + ila_params_lwtunnel(orig_dst->lwtstate), 51 + true); 51 52 52 53 if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) { 53 54 /* Already have a next hop address in route, no need for ··· 101 98 static int ila_input(struct sk_buff *skb) 102 99 { 103 100 struct dst_entry *dst = skb_dst(skb); 101 + struct ila_lwt *ilwt = ila_lwt_lwtunnel(dst->lwtstate); 104 102 105 103 if (skb->protocol != htons(ETH_P_IPV6)) 106 104 goto drop; 107 105 108 - ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate), false); 106 + if (!ilwt->lwt_output) 107 + ila_update_ipv6_locator(skb, 108 + ila_params_lwtunnel(dst->lwtstate), 109 + false); 109 110 110 111 return dst->lwtstate->orig_input(skb); 111 112 ··· 121 114 static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { 122 115 [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, 123 116 [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, 117 + [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, }, 118 + [ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, }, 124 119 }; 125 120 126 121 static int ila_build_state(struct nlattr *nla, ··· 136 127 struct lwtunnel_state *newts; 137 128 const struct fib6_config *cfg6 = cfg; 138 129 struct ila_addr *iaddr; 130 + u8 ident_type = ILA_ATYPE_USE_FORMAT; 131 + u8 hook_type = ILA_HOOK_ROUTE_OUTPUT; 132 + u8 csum_mode = ILA_CSUM_NO_ACTION; 133 + bool lwt_output = true; 134 + u8 eff_ident_type; 139 135 int ret; 140 136 141 137 if (family != AF_INET6) 142 138 return -EINVAL; 143 - 144 - if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) { 145 - /* Need to have full locator and at least type field 146 - * included in destination 147 - */ 148 - return -EINVAL; 149 - } 150 - 151 - iaddr = (struct ila_addr *)&cfg6->fc_dst; 152 - 153 - if (!ila_addr_is_ila(iaddr) || ila_csum_neutral_set(iaddr->ident)) { 154 - /* Don't allow translation for a non-ILA address or checksum 155 - * neutral flag to be set. 156 - */ 157 - return -EINVAL; 158 - } 159 139 160 140 ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack); 161 141 if (ret < 0) ··· 152 154 153 155 if (!tb[ILA_ATTR_LOCATOR]) 154 156 return -EINVAL; 157 + 158 + iaddr = (struct ila_addr *)&cfg6->fc_dst; 159 + 160 + if (tb[ILA_ATTR_IDENT_TYPE]) 161 + ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]); 162 + 163 + if (ident_type == ILA_ATYPE_USE_FORMAT) { 164 + /* Infer identifier type from type field in formatted 165 + * identifier. 166 + */ 167 + 168 + if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) { 169 + /* Need to have full locator and at least type field 170 + * included in destination 171 + */ 172 + return -EINVAL; 173 + } 174 + 175 + eff_ident_type = iaddr->ident.type; 176 + } else { 177 + eff_ident_type = ident_type; 178 + } 179 + 180 + switch (eff_ident_type) { 181 + case ILA_ATYPE_IID: 182 + /* Don't allow ILA for IID type */ 183 + return -EINVAL; 184 + case ILA_ATYPE_LUID: 185 + break; 186 + case ILA_ATYPE_VIRT_V4: 187 + case ILA_ATYPE_VIRT_UNI_V6: 188 + case ILA_ATYPE_VIRT_MULTI_V6: 189 + case ILA_ATYPE_NONLOCAL_ADDR: 190 + /* These ILA formats are not supported yet. */ 191 + default: 192 + return -EINVAL; 193 + } 194 + 195 + if (tb[ILA_ATTR_HOOK_TYPE]) 196 + hook_type = nla_get_u8(tb[ILA_ATTR_HOOK_TYPE]); 197 + 198 + switch (hook_type) { 199 + case ILA_HOOK_ROUTE_OUTPUT: 200 + lwt_output = true; 201 + break; 202 + case ILA_HOOK_ROUTE_INPUT: 203 + lwt_output = false; 204 + break; 205 + default: 206 + return -EINVAL; 207 + } 208 + 209 + if (tb[ILA_ATTR_CSUM_MODE]) 210 + csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]); 211 + 212 + if (csum_mode == ILA_CSUM_NEUTRAL_MAP && 213 + ila_csum_neutral_set(iaddr->ident)) { 214 + /* Don't allow translation if checksum neutral bit is 215 + * configured and it's set in the SIR address. 216 + */ 217 + return -EINVAL; 218 + } 155 219 156 220 newts = lwtunnel_state_alloc(sizeof(*ilwt)); 157 221 if (!newts) ··· 226 166 return ret; 227 167 } 228 168 169 + ilwt->lwt_output = !!lwt_output; 170 + 229 171 p = ila_params_lwtunnel(newts); 230 172 173 + p->csum_mode = csum_mode; 174 + p->ident_type = ident_type; 231 175 p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]); 232 176 233 177 /* Precompute checksum difference for translation since we 234 178 * know both the old locator and the new one. 235 179 */ 236 180 p->locator_match = iaddr->loc; 237 - p->csum_diff = compute_csum_diff8( 238 - (__be32 *)&p->locator_match, (__be32 *)&p->locator); 239 - 240 - if (tb[ILA_ATTR_CSUM_MODE]) 241 - p->csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]); 242 181 243 182 ila_init_saved_csum(p); 244 183 ··· 262 203 struct lwtunnel_state *lwtstate) 263 204 { 264 205 struct ila_params *p = ila_params_lwtunnel(lwtstate); 206 + struct ila_lwt *ilwt = ila_lwt_lwtunnel(lwtstate); 265 207 266 208 if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64, 267 209 ILA_ATTR_PAD)) 268 210 goto nla_put_failure; 211 + 269 212 if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode)) 213 + goto nla_put_failure; 214 + 215 + if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE, (__force u8)p->ident_type)) 216 + goto nla_put_failure; 217 + 218 + if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE, 219 + ilwt->lwt_output ? ILA_HOOK_ROUTE_OUTPUT : 220 + ILA_HOOK_ROUTE_INPUT)) 270 221 goto nla_put_failure; 271 222 272 223 return 0; ··· 289 220 { 290 221 return nla_total_size_64bit(sizeof(u64)) + /* ILA_ATTR_LOCATOR */ 291 222 nla_total_size(sizeof(u8)) + /* ILA_ATTR_CSUM_MODE */ 223 + nla_total_size(sizeof(u8)) + /* ILA_ATTR_IDENT_TYPE */ 224 + nla_total_size(sizeof(u8)) + /* ILA_ATTR_HOOK_TYPE */ 292 225 0; 293 226 } 294 227
+18 -8
net/ipv6/ila/ila_xlat.c
··· 121 121 [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, 122 122 [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, 123 123 [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, 124 + [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, }, 124 125 }; 125 126 126 127 static int parse_nl_config(struct genl_info *info, ··· 139 138 140 139 if (info->attrs[ILA_ATTR_CSUM_MODE]) 141 140 xp->ip.csum_mode = nla_get_u8(info->attrs[ILA_ATTR_CSUM_MODE]); 141 + else 142 + xp->ip.csum_mode = ILA_CSUM_NO_ACTION; 143 + 144 + if (info->attrs[ILA_ATTR_IDENT_TYPE]) 145 + xp->ip.ident_type = nla_get_u8( 146 + info->attrs[ILA_ATTR_IDENT_TYPE]); 147 + else 148 + xp->ip.ident_type = ILA_ATYPE_USE_FORMAT; 142 149 143 150 if (info->attrs[ILA_ATTR_IFINDEX]) 144 151 xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); ··· 207 198 } 208 199 } 209 200 210 - static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral); 201 + static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila); 211 202 212 203 static unsigned int 213 204 ila_nf_input(void *priv, ··· 405 396 (__force u64)ila->xp.ip.locator_match.v64, 406 397 ILA_ATTR_PAD) || 407 398 nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) || 408 - nla_put_u32(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode)) 399 + nla_put_u8(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode) || 400 + nla_put_u8(msg, ILA_ATTR_IDENT_TYPE, ila->xp.ip.ident_type)) 409 401 return -1; 410 402 411 403 return 0; ··· 617 607 .size = sizeof(struct ila_net), 618 608 }; 619 609 620 - static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral) 610 + static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila) 621 611 { 622 612 struct ila_map *ila; 623 613 struct ipv6hdr *ip6h = ipv6_hdr(skb); ··· 627 617 628 618 /* Assumes skb contains a valid IPv6 header that is pulled */ 629 619 630 - if (!ila_addr_is_ila(iaddr)) { 631 - /* Type indicates this is not an ILA address */ 632 - return 0; 633 - } 620 + /* No check here that ILA type in the mapping matches what is in the 621 + * address. We assume that whatever sender gaves us can be translated. 622 + * The checksum mode however is relevant. 623 + */ 634 624 635 625 rcu_read_lock(); 636 626 637 627 ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan); 638 628 if (ila) 639 - ila_update_ipv6_locator(skb, &ila->xp.ip, set_csum_neutral); 629 + ila_update_ipv6_locator(skb, &ila->xp.ip, sir2ila); 640 630 641 631 rcu_read_unlock(); 642 632