ip2mac.c (4b7cbb46) | ip2mac.c (bd670b35) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 4 unchanged lines hidden (view full) --- 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ | 1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 4 unchanged lines hidden (view full) --- 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ |
21 |
|
21/* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26/* 27 * Functions to implement IP address -> link layer address (PSARC 2006/482) 28 */ 29#include <inet/ip2mac.h> 30#include <inet/ip2mac_impl.h> 31#include <sys/zone.h> | 22/* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* 28 * Functions to implement IP address -> link layer address (PSARC 2006/482) 29 */ 30#include <inet/ip2mac.h> 31#include <inet/ip2mac_impl.h> 32#include <sys/zone.h> |
32#include <sys/dlpi.h> | |
33#include <inet/ip_ndp.h> 34#include <inet/ip_if.h> 35#include <inet/ip6.h> 36 37/* 38 * dispatch pending callbacks. 39 */ 40void | 33#include <inet/ip_ndp.h> 34#include <inet/ip_if.h> 35#include <inet/ip6.h> 36 37/* 38 * dispatch pending callbacks. 39 */ 40void |
41nce_cb_dispatch(nce_t *nce) | 41ncec_cb_dispatch(ncec_t *ncec) |
42{ | 42{ |
43 nce_cb_t *nce_cb = list_head(&nce->nce_cb); | 43 ncec_cb_t *ncec_cb; |
44 ip2mac_t ip2m; 45 | 44 ip2mac_t ip2m; 45 |
46 mutex_enter(&nce->nce_lock); 47 if (list_is_empty(&nce->nce_cb)) { 48 mutex_exit(&nce->nce_lock); | 46 mutex_enter(&ncec->ncec_lock); 47 if (list_is_empty(&ncec->ncec_cb)) { 48 mutex_exit(&ncec->ncec_lock); |
49 return; 50 } | 49 return; 50 } |
51 nce_ip2mac_response(&ip2m, nce); 52 nce_cb_refhold_locked(nce); | 51 ncec_ip2mac_response(&ip2m, ncec); 52 ncec_cb_refhold_locked(ncec); |
53 /* 54 * IP does not hold internal locks like nce_lock across calls to 55 * other subsystems for fear of recursive lock entry and lock 56 * hierarchy violation. The caller may be holding locks across 57 * the call to IP. (It would be ideal if no subsystem holds locks 58 * across calls into another subsystem, especially if calls can 59 * happen in either direction). 60 */ | 53 /* 54 * IP does not hold internal locks like nce_lock across calls to 55 * other subsystems for fear of recursive lock entry and lock 56 * hierarchy violation. The caller may be holding locks across 57 * the call to IP. (It would be ideal if no subsystem holds locks 58 * across calls into another subsystem, especially if calls can 59 * happen in either direction). 60 */ |
61 nce_cb = list_head(&nce->nce_cb); 62 for (; nce_cb != NULL; nce_cb = list_next(&nce->nce_cb, nce_cb)) { 63 if (nce_cb->nce_cb_flags & NCE_CB_DISPATCHED) | 61 ncec_cb = list_head(&ncec->ncec_cb); 62 for (; ncec_cb != NULL; ncec_cb = list_next(&ncec->ncec_cb, ncec_cb)) { 63 if (ncec_cb->ncec_cb_flags & NCE_CB_DISPATCHED) |
64 continue; | 64 continue; |
65 nce_cb->nce_cb_flags |= NCE_CB_DISPATCHED; 66 mutex_exit(&nce->nce_lock); 67 (*nce_cb->nce_cb_func)(&ip2m, nce_cb->nce_cb_arg); 68 mutex_enter(&nce->nce_lock); | 65 ncec_cb->ncec_cb_flags |= NCE_CB_DISPATCHED; 66 mutex_exit(&ncec->ncec_lock); 67 (*ncec_cb->ncec_cb_func)(&ip2m, ncec_cb->ncec_cb_arg); 68 mutex_enter(&ncec->ncec_lock); |
69 } | 69 } |
70 nce_cb_refrele(nce); 71 mutex_exit(&nce->nce_lock); | 70 ncec_cb_refrele(ncec); 71 mutex_exit(&ncec->ncec_lock); |
72} 73 74/* 75 * fill up the ip2m response fields with inforamation from the nce. 76 */ 77void | 72} 73 74/* 75 * fill up the ip2m response fields with inforamation from the nce. 76 */ 77void |
78nce_ip2mac_response(ip2mac_t *ip2m, nce_t *nce) | 78ncec_ip2mac_response(ip2mac_t *ip2m, ncec_t *ncec) |
79{ | 79{ |
80 boolean_t isv6 = (nce->nce_ipversion == IPV6_VERSION); | 80 boolean_t isv6 = (ncec->ncec_ipversion == IPV6_VERSION); 81 sin_t *sin; |
81 sin6_t *sin6; 82 struct sockaddr_dl *sdl; | 82 sin6_t *sin6; 83 struct sockaddr_dl *sdl; |
83 uchar_t *nce_lladdr; | |
84 | 84 |
85 ASSERT(MUTEX_HELD(&nce->nce_lock)); | 85 ASSERT(MUTEX_HELD(&ncec->ncec_lock)); |
86 bzero(ip2m, sizeof (*ip2m)); | 86 bzero(ip2m, sizeof (*ip2m)); |
87 if (NCE_ISREACHABLE(nce) && (nce->nce_flags & NCE_F_CONDEMNED) == 0) | 87 if (NCE_ISREACHABLE(ncec) && !NCE_ISCONDEMNED(ncec)) |
88 ip2m->ip2mac_err = 0; 89 else 90 ip2m->ip2mac_err = ESRCH; 91 if (isv6) { 92 sin6 = (sin6_t *)&ip2m->ip2mac_pa; 93 sin6->sin6_family = AF_INET6; | 88 ip2m->ip2mac_err = 0; 89 else 90 ip2m->ip2mac_err = ESRCH; 91 if (isv6) { 92 sin6 = (sin6_t *)&ip2m->ip2mac_pa; 93 sin6->sin6_family = AF_INET6; |
94 sin6->sin6_addr = nce->nce_addr; | 94 sin6->sin6_addr = ncec->ncec_addr; 95 } else { 96 sin = (sin_t *)&ip2m->ip2mac_pa; 97 sin->sin_family = AF_INET; 98 IN6_V4MAPPED_TO_INADDR(&ncec->ncec_addr, &sin->sin_addr); |
95 } 96 if (ip2m->ip2mac_err == 0) { 97 sdl = &ip2m->ip2mac_ha; 98 sdl->sdl_family = AF_LINK; | 99 } 100 if (ip2m->ip2mac_err == 0) { 101 sdl = &ip2m->ip2mac_ha; 102 sdl->sdl_family = AF_LINK; |
99 sdl->sdl_type = nce->nce_ill->ill_type; | 103 sdl->sdl_type = ncec->ncec_ill->ill_type; 104 /* 105 * should we put ncec_ill->ill_name in there? why? 106 * likewise for the sdl_index 107 */ |
100 sdl->sdl_nlen = 0; | 108 sdl->sdl_nlen = 0; |
101 sdl->sdl_alen = nce->nce_ill->ill_phys_addr_length; 102 nce_lladdr = nce->nce_res_mp->b_rptr + 103 NCE_LL_ADDR_OFFSET(nce->nce_ill); 104 bcopy(nce_lladdr, LLADDR(sdl), sdl->sdl_alen); | 109 sdl->sdl_alen = ncec->ncec_ill->ill_phys_addr_length; 110 if (ncec->ncec_lladdr != NULL) 111 bcopy(ncec->ncec_lladdr, LLADDR(sdl), sdl->sdl_alen); |
105 } 106} 107 108void | 112 } 113} 114 115void |
109nce_cb_refhold_locked(nce_t *nce) | 116ncec_cb_refhold_locked(ncec_t *ncec) |
110{ | 117{ |
111 ASSERT(MUTEX_HELD(&nce->nce_lock)); 112 nce->nce_cb_walker_cnt++; | 118 ASSERT(MUTEX_HELD(&ncec->ncec_lock)); 119 ncec->ncec_cb_walker_cnt++; |
113} 114 115void | 120} 121 122void |
116nce_cb_refrele(nce_t *nce) | 123ncec_cb_refrele(ncec_t *ncec) |
117{ | 124{ |
118 nce_cb_t *nce_cb, *nce_cb_next = NULL; | 125 ncec_cb_t *ncec_cb, *ncec_cb_next = NULL; |
119 | 126 |
120 ASSERT(MUTEX_HELD(&nce->nce_lock)); 121 if (--nce->nce_cb_walker_cnt == 0) { 122 for (nce_cb = list_head(&nce->nce_cb); nce_cb != NULL; 123 nce_cb = nce_cb_next) { | 127 ASSERT(MUTEX_HELD(&ncec->ncec_lock)); 128 if (--ncec->ncec_cb_walker_cnt == 0) { 129 for (ncec_cb = list_head(&ncec->ncec_cb); ncec_cb != NULL; 130 ncec_cb = ncec_cb_next) { |
124 | 131 |
125 nce_cb_next = list_next(&nce->nce_cb, nce_cb); 126 if ((nce_cb->nce_cb_flags & NCE_CB_DISPATCHED) == 0) | 132 ncec_cb_next = list_next(&ncec->ncec_cb, ncec_cb); 133 if ((ncec_cb->ncec_cb_flags & NCE_CB_DISPATCHED) == 0) |
127 continue; | 134 continue; |
128 list_remove(&nce->nce_cb, nce_cb); 129 kmem_free(nce_cb, sizeof (*nce_cb)); | 135 list_remove(&ncec->ncec_cb, ncec_cb); 136 kmem_free(ncec_cb, sizeof (*ncec_cb)); |
130 } 131 } 132} 133 134/* 135 * add a callback to the nce, so that the callback can be invoked 136 * after address resolution succeeds/fails. 137 */ 138static ip2mac_id_t | 137 } 138 } 139} 140 141/* 142 * add a callback to the nce, so that the callback can be invoked 143 * after address resolution succeeds/fails. 144 */ 145static ip2mac_id_t |
139nce_add_cb(nce_t *nce, ip2mac_callback_t *cb, void *cbarg) | 146ncec_add_cb(ncec_t *ncec, ip2mac_callback_t *cb, void *cbarg) |
140{ | 147{ |
141 nce_cb_t *nce_cb; | 148 ncec_cb_t *nce_cb; |
142 ip2mac_id_t ip2mid = NULL; 143 | 149 ip2mac_id_t ip2mid = NULL; 150 |
144 ASSERT(MUTEX_HELD(&nce->nce_lock)); | 151 ASSERT(MUTEX_HELD(&ncec->ncec_lock)); |
145 if ((nce_cb = kmem_zalloc(sizeof (*nce_cb), KM_NOSLEEP)) == NULL) 146 return (ip2mid); | 152 if ((nce_cb = kmem_zalloc(sizeof (*nce_cb), KM_NOSLEEP)) == NULL) 153 return (ip2mid); |
147 nce_cb->nce_cb_func = cb; 148 nce_cb->nce_cb_arg = cbarg; | 154 nce_cb->ncec_cb_func = cb; 155 nce_cb->ncec_cb_arg = cbarg; |
149 /* | 156 /* |
150 * We identify the nce_cb_t during cancellation by the address | 157 * We identify the ncec_cb_t during cancellation by the address |
151 * of the nce_cb_t itself, and, as a short-cut for eliminating | 158 * of the nce_cb_t itself, and, as a short-cut for eliminating |
152 * clear mismatches, only look in the callback list of nce's | 159 * clear mismatches, only look in the callback list of ncec's |
153 * whose address is equal to the nce_cb_id. 154 */ | 160 * whose address is equal to the nce_cb_id. 161 */ |
155 nce_cb->nce_cb_id = nce; /* no refs! just an address */ 156 list_insert_tail(&nce->nce_cb, nce_cb); 157 ip2mid = nce; /* this is the id to be used in ip2mac_cancel */ | 162 nce_cb->ncec_cb_id = ncec; /* no refs! just an address */ 163 list_insert_tail(&ncec->ncec_cb, nce_cb); 164 ip2mid = ncec; /* this is the id to be used in ip2mac_cancel */ |
158 159 return (nce_cb); 160} 161 162/* 163 * Resolve an IP address to a link-layer address using the data-structures 164 * defined in PSARC 2006/482. If the current link-layer address for the 165 * IP address is not known, the state-machine for resolving the resolution 166 * will be triggered, and the callback function (*cb) will be invoked after 167 * the resolution completes. 168 */ 169ip2mac_id_t | 165 166 return (nce_cb); 167} 168 169/* 170 * Resolve an IP address to a link-layer address using the data-structures 171 * defined in PSARC 2006/482. If the current link-layer address for the 172 * IP address is not known, the state-machine for resolving the resolution 173 * will be triggered, and the callback function (*cb) will be invoked after 174 * the resolution completes. 175 */ 176ip2mac_id_t |
170ip2mac(uint_t flags, ip2mac_t *ip2m, ip2mac_callback_t *cb, void *cbarg, | 177ip2mac(uint_t op, ip2mac_t *ip2m, ip2mac_callback_t *cb, void *cbarg, |
171 zoneid_t zoneid) 172{ | 178 zoneid_t zoneid) 179{ |
173 nce_t *nce; | 180 ncec_t *ncec; 181 nce_t *nce = NULL; |
174 boolean_t isv6; 175 ill_t *ill; 176 netstack_t *ns; 177 ip_stack_t *ipst; 178 ip2mac_id_t ip2mid = NULL; | 182 boolean_t isv6; 183 ill_t *ill; 184 netstack_t *ns; 185 ip_stack_t *ipst; 186 ip2mac_id_t ip2mid = NULL; |
187 sin_t *sin; |
|
179 sin6_t *sin6; 180 int err; 181 uint64_t delta; | 188 sin6_t *sin6; 189 int err; 190 uint64_t delta; |
191 boolean_t need_resolve = B_FALSE; |
|
182 183 isv6 = (ip2m->ip2mac_pa.ss_family == AF_INET6); 184 | 192 193 isv6 = (ip2m->ip2mac_pa.ss_family == AF_INET6); 194 |
185 if (!isv6) { 186 /* 187 * IPv4 is not currently supported. 188 */ 189 ip2m->ip2mac_err = ENOTSUP; 190 return (NULL); 191 } 192 | |
193 ns = netstack_find_by_zoneid(zoneid); 194 if (ns == NULL) { 195 ip2m->ip2mac_err = EINVAL; 196 return (NULL); 197 } 198 /* 199 * For exclusive stacks we reset the zoneid to zero 200 * since IP uses the global zoneid in the exclusive stacks. 201 */ 202 if (ns->netstack_stackid != GLOBAL_NETSTACKID) 203 zoneid = GLOBAL_ZONEID; 204 ipst = ns->netstack_ip; 205 /* 206 * find the ill from the ip2m->ip2mac_ifindex 207 */ | 195 ns = netstack_find_by_zoneid(zoneid); 196 if (ns == NULL) { 197 ip2m->ip2mac_err = EINVAL; 198 return (NULL); 199 } 200 /* 201 * For exclusive stacks we reset the zoneid to zero 202 * since IP uses the global zoneid in the exclusive stacks. 203 */ 204 if (ns->netstack_stackid != GLOBAL_NETSTACKID) 205 zoneid = GLOBAL_ZONEID; 206 ipst = ns->netstack_ip; 207 /* 208 * find the ill from the ip2m->ip2mac_ifindex 209 */ |
208 ill = ill_lookup_on_ifindex(ip2m->ip2mac_ifindex, isv6, NULL, 209 NULL, NULL, NULL, ipst); | 210 ill = ill_lookup_on_ifindex(ip2m->ip2mac_ifindex, isv6, ipst); |
210 if (ill == NULL) { 211 ip2m->ip2mac_err = ENXIO; 212 netstack_rele(ns); 213 return (NULL); 214 } 215 if (isv6) { 216 sin6 = (sin6_t *)&ip2m->ip2mac_pa; | 211 if (ill == NULL) { 212 ip2m->ip2mac_err = ENXIO; 213 netstack_rele(ns); 214 return (NULL); 215 } 216 if (isv6) { 217 sin6 = (sin6_t *)&ip2m->ip2mac_pa; |
217 if (flags == IP2MAC_LOOKUP) { 218 nce = ndp_lookup_v6(ill, B_FALSE, &sin6->sin6_addr, 219 B_FALSE); | 218 if (op == IP2MAC_LOOKUP) { 219 nce = nce_lookup_v6(ill, &sin6->sin6_addr); |
220 } else { | 220 } else { |
221 err = ndp_lookup_then_add_v6(ill, B_FALSE, NULL, 222 &sin6->sin6_addr, &ipv6_all_ones, &ipv6_all_zeros, 223 0, 0, ND_INCOMPLETE, &nce); | 221 err = nce_lookup_then_add_v6(ill, NULL, 222 ill->ill_phys_addr_length, 223 &sin6->sin6_addr, 0, ND_UNCHANGED, &nce); |
224 } 225 } else { | 224 } 225 } else { |
226 ip2m->ip2mac_err = ENOTSUP; /* yet. */ 227 goto done; | 226 sin = (sin_t *)&ip2m->ip2mac_pa; 227 if (op == IP2MAC_LOOKUP) { 228 nce = nce_lookup_v4(ill, &sin->sin_addr.s_addr); 229 } else { 230 err = nce_lookup_then_add_v4(ill, NULL, 231 ill->ill_phys_addr_length, 232 &sin->sin_addr.s_addr, 0, ND_UNCHANGED, &nce); 233 } |
228 } | 234 } |
229 if (flags == IP2MAC_LOOKUP) { | 235 if (op == IP2MAC_LOOKUP) { |
230 if (nce == NULL) { 231 ip2m->ip2mac_err = ESRCH; 232 goto done; 233 } | 236 if (nce == NULL) { 237 ip2m->ip2mac_err = ESRCH; 238 goto done; 239 } |
234 mutex_enter(&nce->nce_lock); 235 if (NCE_ISREACHABLE(nce)) { 236 nce_ip2mac_response(ip2m, nce); | 240 ncec = nce->nce_common; 241 delta = TICK_TO_MSEC(lbolt64) - ncec->ncec_last; 242 mutex_enter(&ncec->ncec_lock); 243 if (NCE_ISREACHABLE(ncec) && 244 delta < (uint64_t)ill->ill_reachable_time) { 245 ncec_ip2mac_response(ip2m, ncec); |
237 ip2m->ip2mac_err = 0; 238 } else { 239 ip2m->ip2mac_err = ESRCH; 240 } | 246 ip2m->ip2mac_err = 0; 247 } else { 248 ip2m->ip2mac_err = ESRCH; 249 } |
241 mutex_exit(&nce->nce_lock); 242 NCE_REFRELE(nce); | 250 mutex_exit(&ncec->ncec_lock); |
243 goto done; 244 } else { 245 if (err != 0 && err != EEXIST) { 246 ip2m->ip2mac_err = err; 247 goto done; 248 } 249 } | 251 goto done; 252 } else { 253 if (err != 0 && err != EEXIST) { 254 ip2m->ip2mac_err = err; 255 goto done; 256 } 257 } |
250 delta = TICK_TO_MSEC(lbolt64) - nce->nce_last; 251 mutex_enter(&nce->nce_lock); 252 if (nce->nce_flags & NCE_F_CONDEMNED) { | 258 ncec = nce->nce_common; 259 delta = TICK_TO_MSEC(lbolt64) - ncec->ncec_last; 260 mutex_enter(&ncec->ncec_lock); 261 if (NCE_ISCONDEMNED(ncec)) { |
253 ip2m->ip2mac_err = ESRCH; | 262 ip2m->ip2mac_err = ESRCH; |
254 } else if (!NCE_ISREACHABLE(nce) || 255 delta > (uint64_t)ill->ill_reachable_time) { 256 if (NCE_ISREACHABLE(nce)) { | 263 } else { 264 if (NCE_ISREACHABLE(ncec)) { 265 if (NCE_MYADDR(ncec) || 266 delta < (uint64_t)ill->ill_reachable_time) { 267 ncec_ip2mac_response(ip2m, ncec); 268 ip2m->ip2mac_err = 0; 269 mutex_exit(&ncec->ncec_lock); 270 goto done; 271 } |
257 /* 258 * Since we do not control the packet output 259 * path for ip2mac() callers, we need to verify 260 * if the existing information in the nce is 261 * very old, and retrigger resolution if necessary. 262 * We will not return the existing stale 263 * information until it is verified through a 264 * resolver request/response exchange. 265 * 266 * In the future, we may want to support extensions 267 * that do additional callbacks on link-layer updates, 268 * so that we can return the stale information but 269 * also update the caller if the lladdr changes. 270 */ | 272 /* 273 * Since we do not control the packet output 274 * path for ip2mac() callers, we need to verify 275 * if the existing information in the nce is 276 * very old, and retrigger resolution if necessary. 277 * We will not return the existing stale 278 * information until it is verified through a 279 * resolver request/response exchange. 280 * 281 * In the future, we may want to support extensions 282 * that do additional callbacks on link-layer updates, 283 * so that we can return the stale information but 284 * also update the caller if the lladdr changes. 285 */ |
271 nce->nce_rcnt = ill->ill_xmit_count; 272 nce->nce_state = ND_PROBE; 273 err = 0; /* treat this nce as a new one */ | 286 ncec->ncec_rcnt = ill->ill_xmit_count; 287 ncec->ncec_state = ND_PROBE; 288 need_resolve = B_TRUE; /* reachable but very old nce */ 289 } else if (ncec->ncec_state == ND_INITIAL) { 290 need_resolve = B_TRUE; /* ND_INITIAL nce */ 291 ncec->ncec_state = ND_INCOMPLETE; |
274 } | 292 } |
275 if (nce->nce_rcnt > 0) { | 293 /* 294 * NCE not known to be reachable in the recent past. We must 295 * reconfirm the information before returning it to the caller 296 */ 297 if (ncec->ncec_rcnt > 0) { |
276 /* | 298 /* |
277 * Still resolving this nce, so we can 278 * queue the callback information in nce->nce_cb | 299 * Still resolving this ncec, so we can queue the 300 * callback information in ncec->ncec_cb |
279 */ | 301 */ |
280 ip2mid = nce_add_cb(nce, cb, cbarg); | 302 ip2mid = ncec_add_cb(ncec, cb, cbarg); |
281 ip2m->ip2mac_err = EINPROGRESS; 282 } else { 283 /* | 303 ip2m->ip2mac_err = EINPROGRESS; 304 } else { 305 /* |
284 * Resolution failed. | 306 * No more retransmits allowed -- resolution failed. |
285 */ 286 ip2m->ip2mac_err = ESRCH; 287 } | 307 */ 308 ip2m->ip2mac_err = ESRCH; 309 } |
288 } else { 289 nce_ip2mac_response(ip2m, nce); 290 ip2m->ip2mac_err = 0; | |
291 } | 310 } |
292 if (ip2m->ip2mac_err == EINPROGRESS && err != EEXIST) 293 ip_ndp_resolve(nce); 294 mutex_exit(&nce->nce_lock); 295 NCE_REFRELE(nce); | 311 mutex_exit(&ncec->ncec_lock); |
296done: | 312done: |
313 /* 314 * if NCE_ISREACHABLE(ncec) but very old, or if it is ND_INITIAL, 315 * trigger resolve. 316 */ 317 if (need_resolve) 318 ip_ndp_resolve(ncec); 319 if (nce != NULL) 320 nce_refrele(nce); |
|
297 netstack_rele(ns); 298 ill_refrele(ill); 299 return (ip2mid); 300} 301 302/* | 321 netstack_rele(ns); 322 ill_refrele(ill); 323 return (ip2mid); 324} 325 326/* |
303 * data passed to nce_walk for canceling outstanding callbacks. | 327 * data passed to ncec_walk for canceling outstanding callbacks. |
304 */ 305typedef struct ip2mac_cancel_data_s { 306 ip2mac_id_t ip2m_cancel_id; 307 int ip2m_cancel_err; 308} ip2mac_cancel_data_t; 309 310/* | 328 */ 329typedef struct ip2mac_cancel_data_s { 330 ip2mac_id_t ip2m_cancel_id; 331 int ip2m_cancel_err; 332} ip2mac_cancel_data_t; 333 334/* |
311 * callback invoked for each active nce. If the ip2mac_id_t corresponds 312 * to an active nce_cb_t in the nce's callback list, we want to remove | 335 * callback invoked for each active ncec. If the ip2mac_id_t corresponds 336 * to an active nce_cb_t in the ncec's callback list, we want to remove |
313 * the callback (if there are no walkers) or return EBUSY to the caller 314 */ 315static int | 337 * the callback (if there are no walkers) or return EBUSY to the caller 338 */ 339static int |
316ip2mac_cancel_callback(nce_t *nce, void *arg) | 340ip2mac_cancel_callback(ncec_t *ncec, void *arg) |
317{ 318 ip2mac_cancel_data_t *ip2m_wdata = arg; | 341{ 342 ip2mac_cancel_data_t *ip2m_wdata = arg; |
319 nce_cb_t *ip2m_nce_cb = ip2m_wdata->ip2m_cancel_id; 320 nce_cb_t *nce_cb; | 343 ncec_cb_t *ip2m_nce_cb = ip2m_wdata->ip2m_cancel_id; 344 ncec_cb_t *ncec_cb; |
321 | 345 |
322 if (ip2m_nce_cb->nce_cb_id != nce) | 346 if (ip2m_nce_cb->ncec_cb_id != ncec) |
323 return (0); 324 | 347 return (0); 348 |
325 mutex_enter(&nce->nce_lock); 326 if (list_is_empty(&nce->nce_cb)) { 327 mutex_exit(&nce->nce_lock); | 349 mutex_enter(&ncec->ncec_lock); 350 if (list_is_empty(&ncec->ncec_cb)) { 351 mutex_exit(&ncec->ncec_lock); |
328 return (0); 329 } 330 /* 331 * IP does not hold internal locks like nce_lock across calls to 332 * other subsystems for fear of recursive lock entry and lock 333 * hierarchy violation. The caller may be holding locks across 334 * the call to IP. (It would be ideal if no subsystem holds locks 335 * across calls into another subsystem, especially if calls can 336 * happen in either direction). 337 */ | 352 return (0); 353 } 354 /* 355 * IP does not hold internal locks like nce_lock across calls to 356 * other subsystems for fear of recursive lock entry and lock 357 * hierarchy violation. The caller may be holding locks across 358 * the call to IP. (It would be ideal if no subsystem holds locks 359 * across calls into another subsystem, especially if calls can 360 * happen in either direction). 361 */ |
338 nce_cb = list_head(&nce->nce_cb); 339 for (; nce_cb != NULL; nce_cb = list_next(&nce->nce_cb, nce_cb)) { 340 if (nce_cb != ip2m_nce_cb) | 362 ncec_cb = list_head(&ncec->ncec_cb); 363 for (; ncec_cb != NULL; ncec_cb = list_next(&ncec->ncec_cb, ncec_cb)) { 364 if (ncec_cb != ip2m_nce_cb) |
341 continue; 342 /* 343 * If there are no walkers we can remove the nce_cb. 344 * Otherwise the exiting walker will clean up. 345 */ | 365 continue; 366 /* 367 * If there are no walkers we can remove the nce_cb. 368 * Otherwise the exiting walker will clean up. 369 */ |
346 if (nce->nce_cb_walker_cnt == 0) { 347 list_remove(&nce->nce_cb, nce_cb); | 370 if (ncec->ncec_cb_walker_cnt == 0) { 371 list_remove(&ncec->ncec_cb, ncec_cb); |
348 } else { 349 ip2m_wdata->ip2m_cancel_err = EBUSY; 350 } 351 break; 352 } | 372 } else { 373 ip2m_wdata->ip2m_cancel_err = EBUSY; 374 } 375 break; 376 } |
353 mutex_exit(&nce->nce_lock); | 377 mutex_exit(&ncec->ncec_lock); |
354 return (0); 355} 356 357/* 358 * cancel an outstanding timeout set up via ip2mac 359 */ 360int 361ip2mac_cancel(ip2mac_id_t ip2mid, zoneid_t zoneid) --- 12 unchanged lines hidden (view full) --- 374 * since IP uses the global zoneid in the exclusive stacks. 375 */ 376 if (ns->netstack_stackid != GLOBAL_NETSTACKID) 377 zoneid = GLOBAL_ZONEID; 378 ipst = ns->netstack_ip; 379 380 ip2m_wdata.ip2m_cancel_id = ip2mid; 381 ip2m_wdata.ip2m_cancel_err = 0; | 378 return (0); 379} 380 381/* 382 * cancel an outstanding timeout set up via ip2mac 383 */ 384int 385ip2mac_cancel(ip2mac_id_t ip2mid, zoneid_t zoneid) --- 12 unchanged lines hidden (view full) --- 398 * since IP uses the global zoneid in the exclusive stacks. 399 */ 400 if (ns->netstack_stackid != GLOBAL_NETSTACKID) 401 zoneid = GLOBAL_ZONEID; 402 ipst = ns->netstack_ip; 403 404 ip2m_wdata.ip2m_cancel_id = ip2mid; 405 ip2m_wdata.ip2m_cancel_err = 0; |
382 ndp_walk(NULL, ip2mac_cancel_callback, &ip2m_wdata, ipst); | 406 ncec_walk(NULL, ip2mac_cancel_callback, &ip2m_wdata, ipst); |
383 /* 384 * We may return EBUSY if a walk to dispatch callbacks is 385 * in progress, in which case the caller needs to synchronize 386 * with the registered callback function to make sure the 387 * module does not exit when there is a callback pending. 388 */ 389 netstack_rele(ns); 390 return (ip2m_wdata.ip2m_cancel_err); 391} | 407 /* 408 * We may return EBUSY if a walk to dispatch callbacks is 409 * in progress, in which case the caller needs to synchronize 410 * with the registered callback function to make sure the 411 * module does not exit when there is a callback pending. 412 */ 413 netstack_rele(ns); 414 return (ip2m_wdata.ip2m_cancel_err); 415} |