diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/mdb/common/modules/arp/arp.c | 23 | ||||
-rw-r--r-- | usr/src/uts/common/inet/arp/arp.c | 554 | ||||
-rw-r--r-- | usr/src/uts/common/inet/arp_impl.h | 35 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 62 |
4 files changed, 240 insertions, 434 deletions
diff --git a/usr/src/cmd/mdb/common/modules/arp/arp.c b/usr/src/cmd/mdb/common/modules/arp/arp.c index c02c20a268..96178d5a37 100644 --- a/usr/src/cmd/mdb/common/modules/arp/arp.c +++ b/usr/src/cmd/mdb/common/modules/arp/arp.c @@ -215,6 +215,7 @@ ar_describe(const ar_t *ar, char *buf, size_t nbytes, boolean_t addmac) (void) mdb_snprintf(buf, nbytes, "IP %s", name); } else { arl_t arl; + arlphy_t ap; ssize_t retv; uint32_t alen; uchar_t macaddr[ARP_MAX_ADDR_LEN]; @@ -224,11 +225,13 @@ ar_describe(const ar_t *ar, char *buf, size_t nbytes, boolean_t addmac) retv = mdb_snprintf(buf, nbytes, "ARP %s ", arl.arl_name); if (retv >= nbytes || !addmac) return; - alen = arl.arl_hw_addr_length; - if (arl.arl_hw_addr == NULL || alen == 0 || + if (mdb_vread(&ap, sizeof (ap), (uintptr_t)arl.arl_phy) == -1) + return; + alen = ap.ap_hw_addrlen; + if (ap.ap_hw_addr == NULL || alen == 0 || alen > sizeof (macaddr)) return; - if (mdb_vread(macaddr, alen, (uintptr_t)arl.arl_hw_addr) == -1) + if (mdb_vread(macaddr, alen, (uintptr_t)ap.ap_hw_addr) == -1) return; mdb_mac_addr(macaddr, alen, buf + retv, nbytes - retv); } @@ -280,6 +283,7 @@ static int arl_cb(uintptr_t addr, const void *arlptr, void *dummy) { const arl_t *arl = arlptr; + arlphy_t ap; uchar_t macaddr[ARP_MAX_ADDR_LEN]; char macstr[ARP_MAX_ADDR_LEN*3]; char flags[4]; @@ -292,14 +296,15 @@ arl_cb(uintptr_t addr, const void *arlptr, void *dummy) mdb_printf("%16s", primstr); else mdb_printf("%16x", arl->arl_dlpi_pending); - if (arl->arl_hw_addr_length == 0 || - arl->arl_hw_addr_length > sizeof (macaddr)) { + + if (mdb_vread(&ap, sizeof (ap), (uintptr_t)arl->arl_phy) == -1 || + ap.ap_hw_addrlen == 0 || ap.ap_hw_addrlen > sizeof (macaddr)) { (void) strcpy(macstr, "--"); - } else if (mdb_vread(macaddr, arl->arl_hw_addr_length, - (uintptr_t)arl->arl_hw_addr) == -1) { + } else if (mdb_vread(macaddr, ap.ap_hw_addrlen, + (uintptr_t)ap.ap_hw_addr) == -1) { (void) strcpy(macstr, "?"); } else { - mdb_mac_addr(macaddr, arl->arl_hw_addr_length, macstr, + mdb_mac_addr(macaddr, ap.ap_hw_addrlen, macstr, sizeof (macstr)); } @@ -339,7 +344,7 @@ arl_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) { mdb_printf("%<u>%?s %16s %8s %3s %9s %s%</u>\n", "ARL", "DLPI REQ", "DLPI CNT", "FLG", "INTERFACE", - "HW ADDR"); + "HWADDR"); } if (flags & DCMD_ADDRSPEC) { diff --git a/usr/src/uts/common/inet/arp/arp.c b/usr/src/uts/common/inet/arp/arp.c index 4e03b97605..dee240946c 100644 --- a/usr/src/uts/common/inet/arp/arp.c +++ b/usr/src/uts/common/inet/arp/arp.c @@ -157,15 +157,7 @@ typedef struct arpparam_s { char *arp_param_name; } arpparam_t; -typedef struct ar_snmp_hashb { - struct ar_snmp_hashb *ar_next_entry; - mib2_ipNetToMediaEntry_t *ar_snmp_entry; -} ar_snmp_hashb_t; - -static int ar_snmp_hash_size = 64; - typedef struct msg2_args { - ar_snmp_hashb_t *m2a_hashb; mblk_t *m2a_mpdata; mblk_t *m2a_mptail; } msg2_args_t; @@ -183,12 +175,12 @@ static void ar_ce_delete_per_arl(ace_t *ace, void *arg); static ace_t **ar_ce_hash(uint32_t proto, const uchar_t *proto_addr, uint32_t proto_addr_length); static ace_t *ar_ce_lookup(arl_t *arl, uint32_t proto, - uchar_t *proto_addr, uint32_t proto_addr_length); + const uchar_t *proto_addr, uint32_t proto_addr_length); static ace_t *ar_ce_lookup_entry(arl_t *arl, uint32_t proto, - uchar_t *proto_addr, uint32_t proto_addr_length); + const uchar_t *proto_addr, uint32_t proto_addr_length); static ace_t *ar_ce_lookup_from_area(mblk_t *mp, ace_t *matchfn()); static ace_t *ar_ce_lookup_mapping(arl_t *arl, uint32_t proto, - uchar_t *proto_addr, uint32_t proto_addr_length); + const uchar_t *proto_addr, uint32_t proto_addr_length); static boolean_t ar_ce_resolve(ace_t *ace, const uchar_t *hw_addr, uint32_t hw_addr_length); static void ar_ce_walk(void (*pfi)(ace_t *, void *), void *arg1); @@ -197,10 +189,10 @@ static void ar_cleanup(void); static void ar_client_notify(const arl_t *arl, mblk_t *mp, int code); static int ar_close(queue_t *q); static int ar_cmd_dispatch(queue_t *q, mblk_t *mp); +static void ar_cmd_done(arl_t *arl); static mblk_t *ar_dlpi_comm(t_uscalar_t prim, size_t size); static void ar_dlpi_send(arl_t *, mblk_t *); static void ar_dlpi_done(arl_t *, t_uscalar_t); -static void ar_cmd_done(arl_t *arl); static int ar_entry_add(queue_t *q, mblk_t *mp); static int ar_entry_delete(queue_t *q, mblk_t *mp); static int ar_entry_query(queue_t *q, mblk_t *mp); @@ -244,7 +236,6 @@ static void ar_wsrv(queue_t *q); static void ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen, const uchar_t *haddr1, const uchar_t *paddr1, const uchar_t *haddr2, const uchar_t *paddr2, const uchar_t *dstaddr); -static uchar_t *ar_snmp_msg_element(mblk_t **, uchar_t *, size_t); static void ar_cmd_enqueue(arl_t *arl, mblk_t *mp, queue_t *q, ushort_t cmd, boolean_t); static mblk_t *ar_cmd_dequeue(arl_t *arl); @@ -312,8 +303,6 @@ static caddr_t ar_g_nd; /* AR Named Dispatch Head */ * to access data structures in the ARP module without the code being * executed in the context of the IP module, thus there is no locking being * enforced through the use of STREAMS. - * - * */ krwlock_t arl_g_lock; arl_t *arl_g_head; /* ARL List Head */ @@ -405,9 +394,14 @@ ar_ce_create(arl_t *arl, uint_t proto, uchar_t *hw_addr, uint_t hw_addr_len, ace_t **acep; uchar_t *dst; mblk_t *mp; + arlphy_t *ap; if ((flags & ~ACE_EXTERNAL_FLAGS_MASK) || arl == NULL) return (EINVAL); + + if ((ap = arl->arl_phy) == NULL) + return (EINVAL); + if (flags & ACE_F_MYADDR) flags |= ACE_F_PUBLISH | ACE_F_AUTHORITY; @@ -416,8 +410,8 @@ ar_ce_create(arl_t *arl, uint_t proto, uchar_t *hw_addr, uint_t hw_addr_len, /* 224.0.0.0 to zero length address */ flags |= ACE_F_RESOLVED; } else { /* local address and unresolved case */ - if ((hw_addr = arl->arl_hw_addr) != 0) - hw_addr_len = arl->arl_hw_addr_length; + hw_addr = ap->ap_hw_addr; + hw_addr_len = ap->ap_hw_addrlen; if (flags & ACE_F_PUBLISH) flags |= ACE_F_RESOLVED; } @@ -425,13 +419,13 @@ ar_ce_create(arl_t *arl, uint_t proto, uchar_t *hw_addr, uint_t hw_addr_len, flags |= ACE_F_RESOLVED; } - if (!proto_addr || proto_addr_len == 0 || + if (proto_addr == NULL || proto_addr_len == 0 || (proto == IP_ARP_PROTO_TYPE && proto_addr_len != IP_ADDR_LEN)) return (EINVAL); /* Handle hw_addr_len == 0 for DL_ENABMULTI_REQ etc. */ - if (hw_addr_len && !hw_addr) + if (hw_addr_len != 0 && hw_addr == NULL) return (EINVAL); - if (hw_addr_len < arl->arl_hw_addr_length && hw_addr_len != 0) + if (hw_addr_len < ap->ap_hw_addrlen && hw_addr_len != 0) return (EINVAL); if (!proto_extract_mask && (flags & ACE_F_MAPPING)) return (EINVAL); @@ -441,7 +435,7 @@ ar_ce_create(arl_t *arl, uint_t proto, uchar_t *hw_addr, uint_t hw_addr_len, * if we're working with the IPv4 169.254.0.0/16 Link Local Address * space, then don't use the fast timers. Otherwise, use them. */ - if (arl->arl_notifies && + if (ap->ap_notifies && !(proto == IP_ARP_PROTO_TYPE && IS_IPV4_LL_SPACE(proto_addr))) { flags |= ACE_F_FAST; } @@ -496,7 +490,6 @@ ar_ce_create(arl_t *arl, uint_t proto, uchar_t *hw_addr, uint_t hw_addr_len, dst += hw_addr_len; } - ace->ace_arl = arl; ace->ace_flags = flags; if (ar_mask_all_ones(ace->ace_proto_mask, @@ -561,7 +554,7 @@ ar_ce_hash(uint32_t proto, const uchar_t *proto_addr, /* Cache entry lookup. Try to find an ace matching the parameters passed. */ ace_t * -ar_ce_lookup(arl_t *arl, uint32_t proto, uchar_t *proto_addr, +ar_ce_lookup(arl_t *arl, uint32_t proto, const uchar_t *proto_addr, uint32_t proto_addr_length) { ace_t *ace; @@ -578,7 +571,7 @@ ar_ce_lookup(arl_t *arl, uint32_t proto, uchar_t *proto_addr, * Look only for exact entries (no mappings) */ static ace_t * -ar_ce_lookup_entry(arl_t *arl, uint32_t proto, uchar_t *proto_addr, +ar_ce_lookup_entry(arl_t *arl, uint32_t proto, const uchar_t *proto_addr, uint32_t proto_addr_length) { ace_t *ace; @@ -629,7 +622,7 @@ ar_ce_lookup_from_area(mblk_t *mp, ace_t *matchfn()) * Look only for mappings. */ static ace_t * -ar_ce_lookup_mapping(arl_t *arl, uint32_t proto, uchar_t *proto_addr, +ar_ce_lookup_mapping(arl_t *arl, uint32_t proto, const uchar_t *proto_addr, uint32_t proto_addr_length) { ace_t *ace; @@ -942,6 +935,7 @@ static void ar_delete_notify(const ace_t *ace) { const arl_t *arl = ace->ace_arl; + const arlphy_t *ap = arl->arl_phy; mblk_t *mp; size_t len; arh_t *arh; @@ -952,7 +946,7 @@ ar_delete_notify(const ace_t *ace) return; arh = (arh_t *)mp->b_rptr; mp->b_wptr = (uchar_t *)arh + len; - U16_TO_BE16(arl->arl_arp_hw_type, arh->arh_hardware); + U16_TO_BE16(ap->ap_arp_hw_type, arh->arh_hardware); U16_TO_BE16(ace->ace_proto, arh->arh_proto); arh->arh_hlen = 0; arh->arh_plen = ace->ace_proto_addr_length; @@ -1509,19 +1503,21 @@ ar_entry_add(queue_t *q, mblk_t *mp_orig) } if (aflags & ACE_F_PUBLISH) { + arlphy_t *ap = arl->arl_phy; + if (hw_addr == NULL || hw_addr_len == 0) { - hw_addr = arl->arl_hw_addr; + hw_addr = ap->ap_hw_addr; } else if (aflags & ACE_F_MYADDR) { /* * If hardware address changes, then make sure * that the hardware address and hardware - * address length fields in arl_t get updated + * address length fields in arlphy_t get updated * too. Otherwise, they will continue carrying * the old hardware address information. */ ASSERT((hw_addr != NULL) && (hw_addr_len != 0)); - bcopy(hw_addr, arl->arl_hw_addr, hw_addr_len); - arl->arl_hw_addr_length = hw_addr_len; + bcopy(hw_addr, ap->ap_hw_addr, hw_addr_len); + ap->ap_hw_addrlen = hw_addr_len; } ace = ar_ce_lookup(arl, area->area_proto, proto_addr, @@ -1580,7 +1576,7 @@ ar_entry_add(queue_t *q, mblk_t *mp_orig) area_t *, area); ar_xmit(arl, ARP_REQUEST, area->area_proto, proto_addr_len, hw_addr, proto_addr, - arl->arl_arp_addr, proto_addr, NULL); + ap->ap_arp_addr, proto_addr, NULL); ace->ace_last_bcast = ddi_get_lbolt(); /* @@ -1775,9 +1771,9 @@ ar_entry_query(queue_t *q, mblk_t *mp_orig) err = ENXIO; goto err_ret; } - if (arl->arl_xmit_template == NULL) { + if (arl->arl_phy == NULL) { /* Can't get help if we don't know how. */ - DTRACE_PROBE2(query_no_template, ace_t *, ace, + DTRACE_PROBE2(query_no_phy, ace_t *, ace, areq_t *, areq); mpp[0] = NULL; mp->b_prev = NULL; @@ -1787,10 +1783,8 @@ ar_entry_query(queue_t *q, mblk_t *mp_orig) DTRACE_PROBE2(query_unresolved, ace_t, ace, areq_t *, areq); } else { /* No ace yet. Make one now. (This is the common case.) */ - if (areq->areq_xmit_count == 0 || - arl->arl_xmit_template == NULL) { - DTRACE_PROBE2(query_template, arl_t *, arl, - areq_t *, areq); + if (areq->areq_xmit_count == 0 || arl->arl_phy == NULL) { + DTRACE_PROBE2(query_phy, arl_t *, arl, areq_t *, areq); mp->b_prev = NULL; err = ENXIO; goto err_ret; @@ -2062,8 +2056,7 @@ done: } /* - * Enable an interface to - * process of ARP_REQUEST and ARP_RESPONSE messages + * Enable an interface to process ARP_REQUEST and ARP_RESPONSE messages. */ /* ARGSUSED */ static int @@ -2076,9 +2069,9 @@ ar_interface_on(queue_t *q, mblk_t *mp) DTRACE_PROBE2(on_no_arl, queue_t *, q, mblk_t *, mp); return (EINVAL); } - /* Turn off the IFF_NOARP flag and activate ARP */ + DTRACE_PROBE3(on_intf, queue_t *, q, mblk_t *, mp, arl_t *, arl); - arl->arl_flags = 0; + arl->arl_flags &= ~ARL_F_NOARP; return (0); } @@ -2097,9 +2090,9 @@ ar_interface_off(queue_t *q, mblk_t *mp) DTRACE_PROBE2(off_no_arl, queue_t *, q, mblk_t *, mp); return (EINVAL); } - /* Turn on the IFF_NOARP flag and deactivate ARP */ + DTRACE_PROBE3(off_intf, queue_t *, q, mblk_t *, mp, arl_t *, arl); - arl->arl_flags = ARL_F_NOARP; + arl->arl_flags |= ARL_F_NOARP; return (0); } @@ -2190,7 +2183,6 @@ ar_ll_init(ar_t *ar, mblk_t *mp) arl->arl_wq = ar->ar_wq; arl->arl_dlpi_pending = DL_PRIM_INVAL; - arl->arl_link_up = B_TRUE; ar->ar_arl = arl; @@ -2237,7 +2229,7 @@ ar_ll_init(ar_t *ar, mblk_t *mp) * comes back from the device. We set up defaults for all the device dependent * doo-dads we are going to need. This will leave us ready to roll if we are * attempting auto-configuration. Alternatively, these defaults can be - * overidden by initialization procedures possessing higher intelligence. + * overridden by initialization procedures possessing higher intelligence. */ static void ar_ll_set_defaults(arl_t *arl, mblk_t *mp) @@ -2245,20 +2237,20 @@ ar_ll_set_defaults(arl_t *arl, mblk_t *mp) ar_m_t *arm; dl_info_ack_t *dlia = (dl_info_ack_t *)mp->b_rptr; dl_unitdata_req_t *dlur; - int hw_addr_length; - int i1; uchar_t *up; - t_scalar_t sap_length; + arlphy_t *ap; + + ASSERT(arl != NULL); - /* Sanity check... */ - if (arl == NULL) - return; /* - * If we receive multiple DL_INFO_ACkS make sure there are no - * leaks by clearing the defaults now + * Clear any stale defaults that might exist. */ - if (arl->arl_data != NULL ||arl->arl_xmit_template != NULL) - ar_ll_clear_defaults(arl); + ar_ll_clear_defaults(arl); + + ap = kmem_zalloc(sizeof (arlphy_t), KM_NOSLEEP); + if (ap == NULL) + goto bad; + arl->arl_phy = ap; if ((arm = ar_m_lookup(dlia->dl_mac_type)) == NULL) arm = ar_m_lookup(DL_OTHER); @@ -2269,86 +2261,62 @@ ar_ll_set_defaults(arl_t *arl, mblk_t *mp) * exhaustive ar_m_tbl. */ if (dlia->dl_version == DL_VERSION_2) { - hw_addr_length = dlia->dl_brdcst_addr_length; + /* XXX DLPI spec allows dl_sap_length of 0 before binding. */ + ap->ap_saplen = dlia->dl_sap_length; + ap->ap_hw_addrlen = dlia->dl_brdcst_addr_length; } else { - hw_addr_length = arm->ar_mac_hw_addr_length; + ap->ap_saplen = arm->ar_mac_sap_length; + ap->ap_hw_addrlen = arm->ar_mac_hw_addr_length; } - - if ((arl->arl_data = mi_zalloc(2 * hw_addr_length)) == NULL) - goto bad; - - arl->arl_arp_hw_type = arm->ar_mac_arp_hw_type; + ap->ap_arp_hw_type = arm->ar_mac_arp_hw_type; /* - * Someday DLPI will provide the multicast address? Meanwhile we - * assume an address of all ones, known to work on some popular - * networks. + * Allocate the hardware and ARP addresses; note that the hardware + * address cannot be filled in until we see the DL_BIND_ACK. */ - up = (uchar_t *)arl->arl_data; - arl->arl_arp_addr = up; - if (dlia->dl_version == DL_VERSION_2) { - uchar_t *up2; + ap->ap_hw_addr = kmem_zalloc(ap->ap_hw_addrlen, KM_NOSLEEP); + ap->ap_arp_addr = kmem_alloc(ap->ap_hw_addrlen, KM_NOSLEEP); + if (ap->ap_hw_addr == NULL || ap->ap_arp_addr == NULL) + goto bad; - up2 = mi_offset_param(mp, dlia->dl_brdcst_addr_offset, - hw_addr_length); - if (up2 == NULL) + if (dlia->dl_version == DL_VERSION_2) { + if ((up = mi_offset_param(mp, dlia->dl_brdcst_addr_offset, + ap->ap_hw_addrlen)) == NULL) goto bad; - - bcopy(up2, up, hw_addr_length); - up += hw_addr_length; + bcopy(up, ap->ap_arp_addr, ap->ap_hw_addrlen); + } else { /* - * TODO Note that sap_length can be 0 before binding according - * to the DLPI spec. + * No choice but to assume a broadcast address of all ones, + * known to work on some popular networks. */ - sap_length = dlia->dl_sap_length; - } else { - for (i1 = 0; i1 < hw_addr_length; i1++) - *up++ = (char)~0; - sap_length = arm->ar_mac_sap_length; + (void) memset(ap->ap_arp_addr, ~0, ap->ap_hw_addrlen); } - arl->arl_sap_length = sap_length; - - /* - * The hardware address will be filled in when we see the DL_BIND_ACK. - * We reserve space for it here, and make arl_hw_addr point to it. - */ - arl->arl_hw_addr = up; - arl->arl_hw_addr_length = hw_addr_length; - up += arl->arl_hw_addr_length; - /* * Make us a template DL_UNITDATA_REQ message which we will use for * broadcasting resolution requests, and which we will clone to hand * back as responses to the protocols. */ - arl->arl_xmit_template = ar_dlpi_comm(DL_UNITDATA_REQ, - sizeof (dl_unitdata_req_t) + arl->arl_hw_addr_length + - ABS(arl->arl_sap_length)); - if (arl->arl_xmit_template == NULL) + ap->ap_xmit_mp = ar_dlpi_comm(DL_UNITDATA_REQ, ap->ap_hw_addrlen + + ABS(ap->ap_saplen) + sizeof (dl_unitdata_req_t)); + if (ap->ap_xmit_mp == NULL) goto bad; - dlur = (dl_unitdata_req_t *)arl->arl_xmit_template->b_rptr; + dlur = (dl_unitdata_req_t *)ap->ap_xmit_mp->b_rptr; dlur->dl_priority.dl_min = 0; dlur->dl_priority.dl_max = 0; - dlur->dl_dest_addr_length = hw_addr_length + ABS(arl->arl_sap_length); + dlur->dl_dest_addr_length = ap->ap_hw_addrlen + ABS(ap->ap_saplen); dlur->dl_dest_addr_offset = sizeof (dl_unitdata_req_t); - /* Note the destination address offset permanently in the arl. */ - if (arl->arl_sap_length < 0) { - arl->arl_xmit_template_addr_offset = dlur->dl_dest_addr_offset; - arl->arl_xmit_template_sap_offset = dlur->dl_dest_addr_offset + - dlur->dl_dest_addr_length + arl->arl_sap_length; - } else { - /* The sap is first in the address */ - arl->arl_xmit_template_addr_offset = dlur->dl_dest_addr_offset - + arl->arl_sap_length; - arl->arl_xmit_template_sap_offset = dlur->dl_dest_addr_offset; - } - - *(uint16_t *)(arl->arl_xmit_template->b_rptr + - arl->arl_xmit_template_sap_offset) = ETHERTYPE_ARP; + /* NOTE: the destination address and sap offsets are permanently set */ + ap->ap_xmit_sapoff = dlur->dl_dest_addr_offset; + ap->ap_xmit_addroff = dlur->dl_dest_addr_offset; + if (ap->ap_saplen < 0) + ap->ap_xmit_sapoff += ap->ap_hw_addrlen; /* sap last */ + else + ap->ap_xmit_addroff += ap->ap_saplen; /* addr last */ + *(uint16_t *)((caddr_t)dlur + ap->ap_xmit_sapoff) = ETHERTYPE_ARP; return; bad: ar_ll_clear_defaults(arl); @@ -2357,17 +2325,16 @@ bad: static void ar_ll_clear_defaults(arl_t *arl) { - if (arl->arl_data) { - mi_free(arl->arl_data); - arl->arl_data = NULL; - arl->arl_arp_addr = NULL; - arl->arl_sap_length = 0; - arl->arl_hw_addr = NULL; - arl->arl_hw_addr_length = NULL; - } - if (arl->arl_xmit_template) { - freemsg(arl->arl_xmit_template); - arl->arl_xmit_template = NULL; + arlphy_t *ap = arl->arl_phy; + + if (ap != NULL) { + arl->arl_phy = NULL; + if (ap->ap_hw_addr != NULL) + kmem_free(ap->ap_hw_addr, ap->ap_hw_addrlen); + if (ap->ap_arp_addr != NULL) + kmem_free(ap->ap_arp_addr, ap->ap_hw_addrlen); + freemsg(ap->ap_xmit_mp); + kmem_free(ap, sizeof (arlphy_t)); } } @@ -2854,13 +2821,14 @@ ar_query_reply(ace_t *ace, int ret_val, uchar_t *proto_addr, mblk_t *areq_mp; arl_t *arl = ace->ace_arl; mblk_t *mp; - mblk_t *template; + mblk_t *xmit_mp; + arlphy_t *ap = arl->arl_phy; /* Cancel any outstanding timer. */ mi_timer(arl->arl_wq, ace->ace_mp, -1L); /* Establish the return value appropriate. */ if (ret_val == 0) { - if (!ACE_RESOLVED(ace) || arl->arl_xmit_template == NULL) + if (!ACE_RESOLVED(ace) || ap == NULL) ret_val = ENXIO; } /* Terminate all outstanding queries. */ @@ -2875,7 +2843,7 @@ ar_query_reply(ace_t *ace, int ret_val, uchar_t *proto_addr, * template to prepare for the client. */ if (ret_val == 0 && - !(template = copyb(arl->arl_xmit_template))) { + (xmit_mp = copyb(ap->ap_xmit_mp)) == NULL) { /* Too bad, buy more memory. */ ret_val = ENOMEM; } @@ -2891,11 +2859,10 @@ ar_query_reply(ace_t *ace, int ret_val, uchar_t *proto_addr, continue; } /* - * Return the xmit template out with the successful - * IOCTL. + * Return the xmit mp out with the successful IOCTL. */ DB_TYPE(mp) = M_IOCACK; - ioc->ioc_count = template->b_wptr - template->b_rptr; + ioc->ioc_count = MBLKL(xmit_mp); /* Remove the areq mblk from the IOCTL. */ areq_mp = mp->b_cont; mp->b_cont = areq_mp->b_cont; @@ -2918,34 +2885,32 @@ ar_query_reply(ace_t *ace, int ret_val, uchar_t *proto_addr, areq_mp = mp; mp = mp->b_cont; } - if (ABS(arl->arl_sap_length) != 0) { + ASSERT(ret_val == 0 && ap != NULL); + if (ap->ap_saplen != 0) { /* * Copy the SAP type specified in the request into - * the xmit template. + * the xmit mp. */ areq_t *areq = (areq_t *)areq_mp->b_rptr; - bcopy(&areq->areq_sap[0], - (char *)template->b_rptr + - arl->arl_xmit_template_sap_offset, - ABS(arl->arl_sap_length)); + bcopy(areq->areq_sap, xmit_mp->b_rptr + + ap->ap_xmit_sapoff, ABS(ap->ap_saplen)); } /* Done with the areq message. */ freeb(areq_mp); /* - * Copy the resolved hardware address into the xmit template + * Copy the resolved hardware address into the xmit mp * or perform the mapping operation. */ - ar_set_address(ace, (uchar_t *)template->b_rptr - + arl->arl_xmit_template_addr_offset, + ar_set_address(ace, xmit_mp->b_rptr + ap->ap_xmit_addroff, proto_addr, proto_addr_len); /* - * Now insert the xmit template after the response message. In + * Now insert the xmit mp after the response message. In * the M_IOCTL case, it will be the returned data block. In * the M_PROTO case, (again using IP as an example) it will * appear after the IRE and before the outbound packet. */ - template->b_cont = mp->b_cont; - mp->b_cont = template; + xmit_mp->b_cont = mp->b_cont; + mp->b_cont = xmit_mp; putnext(q, mp); } @@ -2954,7 +2919,7 @@ ar_query_reply(ace_t *ace, int ret_val, uchar_t *proto_addr, * cleanup timer or (on error) delete the entry. */ if (!(ace->ace_flags & (ACE_F_PERMANENT | ACE_F_DYING))) { - if (!ACE_RESOLVED(ace) || arl->arl_xmit_template == NULL) { + if (!ACE_RESOLVED(ace) || ap == NULL) { /* * No need to notify IP here, because the entry was * never resolved, so IP can't have any cached copies @@ -3035,8 +3000,8 @@ ar_query_xmit(ace_t *ace, ace_t *src_ace) DTRACE_PROBE3(xmit_send, ace_t *, ace, ace_t *, src_ace, areq_t *, areq); ar_xmit(src_arl, ARP_REQUEST, areq->areq_proto, - areq->areq_sender_addr_length, src_arl->arl_hw_addr, sender_addr, - src_arl->arl_arp_addr, proto_addr, NULL); + areq->areq_sender_addr_length, src_arl->arl_phy->ap_hw_addr, + sender_addr, src_arl->arl_phy->ap_arp_addr, proto_addr, NULL); src_ace->ace_last_bcast = ddi_get_lbolt(); return (areq->areq_xmit_interval); } @@ -3118,7 +3083,7 @@ ar_rput(queue_t *q, mblk_t *mp) ((dl_unitdata_ind_t *)mp->b_rptr)->dl_primitive == DL_UNITDATA_IND) { arl = ((ar_t *)q->q_ptr)->ar_arl; - if (arl != NULL) { + if (arl != NULL && arl->arl_phy != NULL) { /* Real messages from the wire! */ break; } @@ -3198,7 +3163,7 @@ ar_rput(queue_t *q, mblk_t *mp) * for this hardware address type, so might as well discard packets * here that don't match. */ - if ((hlen > 0 && hlen != arl->arl_hw_addr_length) || plen == 0) { + if ((hlen > 0 && hlen != arl->arl_phy->ap_hw_addrlen) || plen == 0) { DTRACE_PROBE2(rput_bogus, arl_t *, arl, mblk_t *, mp1); freemsg(mp); TRACE_2(TR_FAC_ARP, TR_ARP_RPUT_END, @@ -3357,7 +3322,7 @@ ar_rput(queue_t *q, mblk_t *mp) DTRACE_PROBE3(rput_bcast_reply, arl_t *, arl, arh_t *, arh, ace_t *, dst_ace); dst_ace->ace_last_bcast = now; - dstaddr = arl->arl_arp_addr; + dstaddr = arl->arl_phy->ap_arp_addr; /* * If this is one of the long-suffering entries, then * pull it out now. It no longer needs separate @@ -3421,9 +3386,13 @@ ar_rput_dlpi(queue_t *q, mblk_t *mp) { ar_t *ar = q->q_ptr; arl_t *arl = ar->ar_arl; + arlphy_t *ap = NULL; union DL_primitives *dlp; const char *err_str; + if (arl != NULL) + ap = arl->arl_phy; + if (MBLKL(mp) < sizeof (dlp->dl_primitive)) { putnext(q, mp); return; @@ -3472,16 +3441,16 @@ ar_rput_dlpi(queue_t *q, mblk_t *mp) dlp->error_ack.dl_unix_errno); break; case DL_INFO_ACK: - /* - * We have a response back from the driver. Go set up transmit - * defaults. - */ DTRACE_PROBE2(rput_dl_info, arl_t *, arl, dl_info_ack_t *, &dlp->info_ack); - if (arl != NULL) { + if (arl != NULL && arl->arl_dlpi_pending == DL_INFO_REQ) { + /* + * We have a response back from the driver. Go set up + * transmit defaults. + */ ar_ll_set_defaults(arl, mp); ar_dlpi_done(arl, DL_INFO_REQ); - } else { + } else if (arl == NULL) { ar_ll_init(ar, mp); } /* Kick off any awaiting messages */ @@ -3513,35 +3482,39 @@ ar_rput_dlpi(queue_t *q, mblk_t *mp) * We mostly care about interface-up transitions, as this is * when we need to redo duplicate address detection. */ - arl->arl_notifies = - (dlp->notify_ack.dl_notifications & DL_NOTE_LINK_UP) != 0; + if (ap != NULL) { + ap->ap_notifies = (dlp->notify_ack.dl_notifications & + DL_NOTE_LINK_UP) != 0; + } ar_dlpi_done(arl, DL_NOTIFY_REQ); break; case DL_BIND_ACK: DTRACE_PROBE2(rput_dl_bind, arl_t *, arl, dl_bind_ack_t *, &dlp->bind_ack); - if (arl->arl_sap_length < 0) - bcopy((char *)dlp + dlp->bind_ack.dl_addr_offset, - arl->arl_hw_addr, arl->arl_hw_addr_length); - else - bcopy((char *)dlp + dlp->bind_ack.dl_addr_offset + - arl->arl_sap_length, arl->arl_hw_addr, - arl->arl_hw_addr_length); + if (ap != NULL) { + caddr_t hw_addr; + hw_addr = (caddr_t)dlp + dlp->bind_ack.dl_addr_offset; + if (ap->ap_saplen > 0) + hw_addr += ap->ap_saplen; + bcopy(hw_addr, ap->ap_hw_addr, ap->ap_hw_addrlen); + } arl->arl_state = ARL_S_UP; ar_dlpi_done(arl, DL_BIND_REQ); break; case DL_NOTIFY_IND: DTRACE_PROBE2(rput_dl_notify_ind, arl_t *, arl, dl_notify_ind_t *, &dlp->notify_ind); - switch (dlp->notify_ind.dl_notification) { - case DL_NOTE_LINK_UP: - arl->arl_link_up = B_TRUE; - ar_ce_walk(ar_ce_restart_dad, arl); - break; - case DL_NOTE_LINK_DOWN: - arl->arl_link_up = B_FALSE; - break; + if (ap != NULL) { + switch (dlp->notify_ind.dl_notification) { + case DL_NOTE_LINK_UP: + ap->ap_link_down = B_FALSE; + ar_ce_walk(ar_ce_restart_dad, arl); + break; + case DL_NOTE_LINK_DOWN: + ap->ap_link_down = B_TRUE; + break; + } } break; case DL_UDERROR_IND: @@ -3760,57 +3733,14 @@ ar_set_ppa(queue_t *q, mblk_t *mp_orig) return (0); } -/* - * create hash table for comparison. - * The data recvd from IP is hashed on IP address for fast matching. - */ -static ar_snmp_hashb_t * -ar_create_snmp_hash(mblk_t *mpdata) -{ - int entries; - mib2_ipNetToMediaEntry_t *np; - mblk_t *mp1; - ar_snmp_hashb_t *hashb; - ar_snmp_hashb_t *start_entry; - ar_snmp_hashb_t *next_entry; - ar_snmp_hashb_t *ar_snmp_hash_tbl; - - entries = msgdsize(mpdata) / sizeof (mib2_ipNetToMediaEntry_t); - - ar_snmp_hash_tbl = (ar_snmp_hashb_t *)mi_zalloc( - (sizeof (ar_snmp_hashb_t) * (entries + ar_snmp_hash_size))); - if (ar_snmp_hash_tbl == NULL) - return (NULL); - - start_entry = ar_snmp_hash_tbl + ar_snmp_hash_size; - - np = NULL; - mp1 = mpdata; - next_entry = start_entry; - while ((np = (mib2_ipNetToMediaEntry_t *)ar_snmp_msg_element(&mp1, - (uchar_t *)np, sizeof (mib2_ipNetToMediaEntry_t))) != NULL) { - - hashb = &ar_snmp_hash_tbl[IRE_ADDR_HASH - (np->ipNetToMediaNetAddress, ar_snmp_hash_size)]; - ASSERT(next_entry <= start_entry + entries); - next_entry->ar_snmp_entry = np; - next_entry->ar_next_entry = hashb->ar_next_entry; - hashb->ar_next_entry = next_entry; - - next_entry++; - } - return (ar_snmp_hash_tbl); -} - static int ar_snmp_msg(queue_t *q, mblk_t *mp_orig) { - mblk_t *mpdata, *mp = mp_orig; - struct opthdr *optp; - ar_snmp_hashb_t *ar_snmp_hash_tbl; - msg2_args_t args; + mblk_t *mpdata, *mp = mp_orig; + struct opthdr *optp; + msg2_args_t args; - if (!mp) + if (mp == NULL) return (0); /* * ar_cmd_dispatch() already checked for us that "mp->b_cont" is valid @@ -3820,76 +3750,39 @@ ar_snmp_msg(queue_t *q, mblk_t *mp_orig) mp = mp->b_cont; optp = (struct opthdr *)(&mp->b_rptr[sizeof (struct T_optmgmt_ack)]); - if (optp->level != MIB2_IP || optp->name != MIB2_IP_MEDIA) { - putnext(q, mp_orig); - return (EINPROGRESS); - } - /* - * this is an ipNetToMediaTable msg from IP that needs (unique) - * arp cache entries appended... - */ - if ((mpdata = mp->b_cont) == NULL) - return (EINVAL); - - ar_snmp_hash_tbl = ar_create_snmp_hash(mpdata); + if (optp->level == MIB2_IP && optp->name == MIB2_IP_MEDIA) { + /* + * Put our ARP cache entries in the ipNetToMediaTable mp from + * IP. Due to a historical side effect of IP's MIB code, it + * always passes us a b_cont, but the b_cont should be empty. + */ + if ((mpdata = mp->b_cont) == NULL || MBLKL(mpdata) != 0) + return (EINVAL); - if (ar_snmp_hash_tbl != NULL) { - args.m2a_hashb = ar_snmp_hash_tbl; - args.m2a_mpdata = NULL; + args.m2a_mpdata = mpdata; args.m2a_mptail = NULL; ar_ce_walk(ar_snmp_msg2, &args); - - mi_free(ar_snmp_hash_tbl); - /* - * if a new entry was added link it with the list passed in. - */ - if (args.m2a_mpdata != NULL) - linkb(mpdata, args.m2a_mpdata); optp->len = msgdsize(mpdata); } - putnext(q, mp_orig); return (EINPROGRESS); /* so that rput() exits doing nothing... */ } -static uchar_t * -ar_snmp_msg_element(mblk_t **mpp, uchar_t *oldptr, size_t len) -{ - mblk_t *mp; - - mp = *mpp; - if (!mp) - return (NULL); - if (oldptr) - oldptr += len; - else - oldptr = mp->b_rptr; - - if (oldptr + len > mp->b_wptr) { - mp = mp->b_cont; - if (!mp) - return (NULL); - oldptr = mp->b_rptr; - if (oldptr + len > mp->b_wptr) - return (NULL); - } - *mpp = mp; - return (oldptr); -} - static void ar_snmp_msg2(ace_t *ace, void *arg) { const char *name = "unknown"; mib2_ipNetToMediaEntry_t ntme; - ar_snmp_hashb_t *hashb; - mib2_ipNetToMediaEntry_t *np; msg2_args_t *m2ap = arg; - ar_snmp_hashb_t *ar_snmp_hash_tbl; ASSERT(ace != NULL && ace->ace_arl != NULL); if (ace->ace_arl != NULL) name = ace->ace_arl->arl_name; + + /* + * Fill in ntme using the information in the ACE. + */ + ntme.ipNetToMediaType = (ace->ace_flags & ACE_F_PERMANENT) ? 4 : 3; ntme.ipNetToMediaIfIndex.o_length = MIN(OCTET_LENGTH, strlen(name)); bcopy(name, ntme.ipNetToMediaIfIndex.o_bytes, ntme.ipNetToMediaIfIndex.o_length); @@ -3901,68 +3794,19 @@ ar_snmp_msg2(ace_t *ace, void *arg) MIN(OCTET_LENGTH, ace->ace_proto_addr_length); bcopy(ace->ace_proto_mask, ntme.ipNetToMediaInfo.ntm_mask.o_bytes, ntme.ipNetToMediaInfo.ntm_mask.o_length); + ntme.ipNetToMediaInfo.ntm_flags = ace->ace_flags; - ar_snmp_hash_tbl = m2ap->m2a_hashb; - /* - * Append this arp entry only if not already there... - * if found, verify/modify ipNetToMediaType to agree with arp cache - * entry. - * entries within arp cache are unique, so match only with entries - * passed in. - */ - hashb = &ar_snmp_hash_tbl[IRE_ADDR_HASH(ntme.ipNetToMediaNetAddress, - ar_snmp_hash_size)]; - /* - * get the first entry. - */ - hashb = hashb->ar_next_entry; - while (hashb != NULL) { - ASSERT(hashb->ar_snmp_entry != NULL); - np = hashb->ar_snmp_entry; - if (np->ipNetToMediaNetAddress == - ntme.ipNetToMediaNetAddress && - np->ipNetToMediaInfo.ntm_mask.o_length == - ntme.ipNetToMediaInfo.ntm_mask.o_length && - (bcmp(np->ipNetToMediaInfo.ntm_mask.o_bytes, - ntme.ipNetToMediaInfo.ntm_mask.o_bytes, - ntme.ipNetToMediaInfo.ntm_mask.o_length) == 0) && - (bcmp(np->ipNetToMediaIfIndex.o_bytes, - ntme.ipNetToMediaIfIndex.o_bytes, - ntme.ipNetToMediaIfIndex.o_length) == 0)) { - if (ace->ace_flags & ACE_F_PERMANENT) { - /* permanent arp entries are "static" */ - np->ipNetToMediaType = 4; - } - np->ipNetToMediaInfo.ntm_flags = ace->ace_flags; - return; - } - hashb = hashb->ar_next_entry; - } - - /* - * Allocate the first structure, the rest will be allocated - * by snmp_append_data. - */ - if (m2ap->m2a_mpdata == NULL) { - m2ap->m2a_mpdata = allocb(sizeof (mib2_ipNetToMediaEntry_t), - BPRI_HI); - if (m2ap->m2a_mpdata == NULL) { - DTRACE_PROBE(snmp_allocb_failure); - return; - } - } - /* - * ace-> is a new entry to append - */ ntme.ipNetToMediaPhysAddress.o_length = MIN(OCTET_LENGTH, ace->ace_hw_addr_length); if ((ace->ace_flags & ACE_F_RESOLVED) == 0) ntme.ipNetToMediaPhysAddress.o_length = 0; bcopy(ace->ace_hw_addr, ntme.ipNetToMediaPhysAddress.o_bytes, ntme.ipNetToMediaPhysAddress.o_length); - ntme.ipNetToMediaType = (ace->ace_flags & ACE_F_PERMANENT) ? 4 : 3; - ntme.ipNetToMediaInfo.ntm_flags = ace->ace_flags; + /* + * All entries within the ARP cache are unique, and there are no + * preexisting entries in the ipNetToMediaTable mp, so just add 'em. + */ (void) snmp_append_data2(m2ap->m2a_mpdata, &m2ap->m2a_mptail, (char *)&ntme, sizeof (ntme)); } @@ -4048,7 +3892,7 @@ ar_wput(queue_t *q, mblk_t *mp) return; } /* - * The normal behaviour of a STREAMS module should be + * The normal behavior of a STREAMS module should be * to pass down M_FLUSH messages. However there is a * complex sequence of events during plumb/unplumb that * can cause DLPI messages in the driver's queue to be @@ -4112,12 +3956,12 @@ static boolean_t arp_say_ready(ace_t *ace) { mblk_t *mp; - arl_t *arl; + arl_t *arl = ace->ace_arl; + arlphy_t *ap = arl->arl_phy; arh_t *arh; uchar_t *cp; - arl = ace->ace_arl; - mp = allocb(sizeof (*arh) + 2 * (arl->arl_hw_addr_length + + mp = allocb(sizeof (*arh) + 2 * (ace->ace_hw_addr_length + ace->ace_proto_addr_length), BPRI_MED); if (mp == NULL) { /* skip a beat on allocation trouble */ @@ -4127,18 +3971,18 @@ arp_say_ready(ace_t *ace) } /* Tell IP address is now usable */ arh = (arh_t *)mp->b_rptr; - U16_TO_BE16(arl->arl_arp_hw_type, arh->arh_hardware); + U16_TO_BE16(ap->ap_arp_hw_type, arh->arh_hardware); U16_TO_BE16(ace->ace_proto, arh->arh_proto); - arh->arh_hlen = arl->arl_hw_addr_length; + arh->arh_hlen = ace->ace_hw_addr_length; arh->arh_plen = ace->ace_proto_addr_length; U16_TO_BE16(ARP_REQUEST, arh->arh_operation); cp = (uchar_t *)(arh + 1); - bcopy(ace->ace_hw_addr, cp, arl->arl_hw_addr_length); - cp += arl->arl_hw_addr_length; + bcopy(ace->ace_hw_addr, cp, ace->ace_hw_addr_length); + cp += ace->ace_hw_addr_length; bcopy(ace->ace_proto_addr, cp, ace->ace_proto_addr_length); cp += ace->ace_proto_addr_length; - bcopy(ace->ace_hw_addr, cp, arl->arl_hw_addr_length); - cp += arl->arl_hw_addr_length; + bcopy(ace->ace_hw_addr, cp, ace->ace_hw_addr_length); + cp += ace->ace_hw_addr_length; bcopy(ace->ace_proto_addr, cp, ace->ace_proto_addr_length); cp += ace->ace_proto_addr_length; mp->b_wptr = cp; @@ -4191,26 +4035,27 @@ ace_reschedule(ace_t *ace, void *arg) static void arl_reschedule(arl_t *arl) { + arlphy_t *ap = arl->arl_phy; ace_resched_t art; int i; ace_t *ace; - i = arl->arl_defend_count; - arl->arl_defend_count = 0; + i = ap->ap_defend_count; + ap->ap_defend_count = 0; /* If none could be sitting around, then don't reschedule */ if (i < arp_defend_rate) { DTRACE_PROBE1(reschedule_none, arl_t *, arl); return; } art.art_arl = arl; - while (arl->arl_defend_count < arp_defend_rate) { + while (ap->ap_defend_count < arp_defend_rate) { art.art_naces = 0; ar_ce_walk(ace_reschedule, &art); for (i = 0; i < art.art_naces; i++) { ace = art.art_aces[i]; ace->ace_flags |= ACE_F_DELAYED; ace_set_timer(ace, B_FALSE); - if (++arl->arl_defend_count >= arp_defend_rate) + if (++ap->ap_defend_count >= arp_defend_rate) break; } if (art.art_naces < ACE_RESCHED_LIST_LEN) @@ -4229,6 +4074,7 @@ ar_wsrv(queue_t *q) { ace_t *ace; arl_t *arl; + arlphy_t *ap; mblk_t *mp; clock_t ms; @@ -4244,6 +4090,7 @@ ar_wsrv(queue_t *q) if (ace->ace_flags & ACE_F_DYING) continue; arl = ace->ace_arl; + ap = arl->arl_phy; if (ace->ace_flags & ACE_F_UNVERIFIED) { ASSERT(ace->ace_flags & ACE_F_PUBLISH); ASSERT(ace->ace_query_mp == NULL); @@ -4252,7 +4099,7 @@ ar_wsrv(queue_t *q) * will give us the go-ahead to try again when * the link restarts. */ - if (!arl->arl_link_up) { + if (ap->ap_link_down) { DTRACE_PROBE1(timer_link_down, ace_t *, ace); ace->ace_flags |= ACE_F_DAD_ABORTED; @@ -4289,9 +4136,9 @@ ar_wsrv(queue_t *q) */ now = ddi_get_lbolt(); if (arp_defend_rate > 0 && - now - arl->arl_defend_start > + now - ap->ap_defend_start > SEC_TO_TICK(arp_defend_period)) { - arl->arl_defend_start = now; + ap->ap_defend_start = now; arl_reschedule(arl); } /* @@ -4316,9 +4163,8 @@ ar_wsrv(queue_t *q) ace_t *, ace); ace->ace_flags &= ~ACE_F_DELAYED; } else if (arp_defend_rate > 0 && - (arl->arl_defend_count >= arp_defend_rate || - ++arl->arl_defend_count >= - arp_defend_rate)) { + (ap->ap_defend_count >= arp_defend_rate || + ++ap->ap_defend_count >= arp_defend_rate)) { /* * If we're no longer allowed to send * unbidden defense messages, then just @@ -4337,7 +4183,7 @@ ar_wsrv(queue_t *q) ace->ace_proto_addr_length, ace->ace_hw_addr, ace->ace_proto_addr, - arl->arl_arp_addr, + ap->ap_arp_addr, ace->ace_proto_addr, NULL); ace->ace_last_bcast = now; if (ace->ace_xmit_count == 0) @@ -4403,15 +4249,21 @@ ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen, uint8_t *cp; uint_t hlen; mblk_t *mp; + arlphy_t *ap = arl->arl_phy; - /* IFF_NOARP flag is set or interface down: do not send arp messages */ - if ((arl->arl_flags & ARL_F_NOARP) || !arl->arl_link_up) + if (ap == NULL) { + DTRACE_PROBE1(xmit_no_arl_phy, arl_t *, arl); return; + } - mp = arl->arl_xmit_template; - if (mp == NULL || (mp = copyb(mp)) == NULL) + /* IFF_NOARP flag is set or link down: do not send arp messages */ + if ((arl->arl_flags & ARL_F_NOARP) || ap->ap_link_down) return; - hlen = arl->arl_hw_addr_length; + + hlen = ap->ap_hw_addrlen; + if ((mp = copyb(ap->ap_xmit_mp)) == NULL) + return; + mp->b_cont = allocb(AR_LL_HDR_SLACK + ARH_FIXED_LEN + (hlen * 4) + plen + plen, BPRI_MED); if (mp->b_cont == NULL) { @@ -4421,7 +4273,7 @@ ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen, /* Get the L2 destination address for the message */ if (haddr2 == NULL) - dstaddr = arl->arl_arp_addr; + dstaddr = ap->ap_arp_addr; else if (dstaddr == NULL) dstaddr = haddr2; @@ -4429,7 +4281,7 @@ ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen, * Figure out where the target hardware address goes in the * DL_UNITDATA_REQ header, and copy it in. */ - cp = mi_offset_param(mp, arl->arl_xmit_template_addr_offset, hlen); + cp = mi_offset_param(mp, ap->ap_xmit_addroff, hlen); ASSERT(cp != NULL); if (cp == NULL) { freemsg(mp); @@ -4441,7 +4293,7 @@ ar_xmit(arl_t *arl, uint32_t operation, uint32_t proto, uint32_t plen, cp = mp->b_cont->b_rptr + (AR_LL_HDR_SLACK + hlen + hlen); mp->b_cont->b_rptr = cp; arh = (arh_t *)cp; - U16_TO_BE16(arl->arl_arp_hw_type, arh->arh_hardware); + U16_TO_BE16(ap->ap_arp_hw_type, arh->arh_hardware); U16_TO_BE16(proto, arh->arh_proto); arh->arh_hlen = (uint8_t)hlen; arh->arh_plen = (uint8_t)plen; diff --git a/usr/src/uts/common/inet/arp_impl.h b/usr/src/uts/common/inet/arp_impl.h index d8e204d592..c6e12bc86c 100644 --- a/usr/src/uts/common/inet/arp_impl.h +++ b/usr/src/uts/common/inet/arp_impl.h @@ -47,34 +47,37 @@ typedef struct arl_s { queue_t *arl_rq; /* Read queue pointer */ queue_t *arl_wq; /* Write queue pointer */ t_uscalar_t arl_ppa; /* DL_ATTACH parameter */ - uchar_t *arl_arp_addr; /* multicast address to use */ - uchar_t *arl_hw_addr; /* Our hardware address */ - uint32_t arl_hw_addr_length; - uint32_t arl_arp_hw_type; /* Our hardware type */ - t_scalar_t arl_sap_length; char arl_name[LIFNAMSIZ]; /* Lower level name */ - mblk_t *arl_xmit_template; /* DL_UNITDATA_REQ template */ - t_uscalar_t arl_xmit_template_addr_offset; - t_uscalar_t arl_xmit_template_sap_offset; mblk_t *arl_unbind_mp; mblk_t *arl_detach_mp; t_uscalar_t arl_provider_style; /* From DL_INFO_ACK */ mblk_t *arl_queue; /* Queued commands head */ mblk_t *arl_queue_tail; /* Queued commands tail */ - uint32_t arl_flags; /* Used for IFF_NOARP */ + uint32_t arl_flags; /* ARL_F_* values below */ t_uscalar_t arl_dlpi_pending; /* pending DLPI request */ mblk_t *arl_dlpi_deferred; /* Deferred DLPI messages */ uint_t arl_state; /* lower interface state */ - char *arl_data; /* address data pointer */ - clock_t arl_defend_start; /* start of 1-hour period */ - uint_t arl_defend_count; /* # of unbidden broadcasts */ - uint_t - arl_closing : 1, /* stream is closing */ - arl_notifies : 1, /* handles DL_NOTE_LINK */ - arl_link_up : 1; /* DL_NOTE status */ + uint_t arl_closing : 1; /* stream is closing */ uint32_t arl_index; /* instance number */ + struct arlphy_s *arl_phy; /* physical info, if any */ } arl_t; +/* ARL physical info structure for a link level device */ +typedef struct arlphy_s { + uint32_t ap_arp_hw_type; /* hardware type */ + uchar_t *ap_arp_addr; /* multicast address to use */ + uchar_t *ap_hw_addr; /* hardware address */ + uint32_t ap_hw_addrlen; /* hardware address length */ + mblk_t *ap_xmit_mp; /* DL_UNITDATA_REQ template */ + t_uscalar_t ap_xmit_addroff; /* address offset in xmit_mp */ + t_uscalar_t ap_xmit_sapoff; /* sap offset in xmit_mp */ + t_scalar_t ap_saplen; /* sap length */ + clock_t ap_defend_start; /* start of 1-hour period */ + uint_t ap_defend_count; /* # of unbidden broadcasts */ + uint_t ap_notifies : 1, /* handles DL_NOTE_LINK */ + ap_link_down : 1; /* DL_NOTE status */ +} arlphy_t; + extern arl_t *arl_g_head; /* ARL chain head */ extern krwlock_t arl_g_lock; diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 187c4354c6..7896e52d23 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -17749,7 +17749,7 @@ bad_src_route: * - icmp fixed part (mib2_icmp_t) * - ipAddrEntryTable (ip 20) all IPv4 ipifs * - ipRouteEntryTable (ip 21) all IPv4 IREs - * - ipNetToMediaEntryTable (ip 22) IPv4 IREs for on-link destinations + * - ipNetToMediaEntryTable (ip 22) [filled in by the arp module] * - ipRouteAttributeTable (ip 102) labeled routes * - ip multicast membership (ip_member_t) * - ip multicast source filtering (ip_grpsrc_t) @@ -17768,8 +17768,8 @@ bad_src_route: * - ipv6 multicast membership (ipv6_member_t) * - ipv6 multicast source filtering (ipv6_grpsrc_t) * - * IP_ROUTE and IP_MEDIA are augmented in arp to include arp cache entries not - * already present. + * MIB2_IP_MEDIA is filled in by the arp module with ARP cache entries. + * * NOTE: original mpctl is copied for msg's 2..N, since its ctl part is * already filled in by the caller. * Return value of 0 indicates that no messages were sent and caller @@ -18754,17 +18754,14 @@ ip_snmp_get_mib2_icmp6(queue_t *q, mblk_t *mpctl) /* * ire_walk routine to create both ipRouteEntryTable and - * ipNetToMediaEntryTable in one IRE walk + * ipRouteAttributeTable in one IRE walk */ static void ip_snmp_get2_v4(ire_t *ire, iproutedata_t *ird) { ill_t *ill; ipif_t *ipif; - mblk_t *llmp; - dl_unitdata_req_t *dlup; mib2_ipRouteEntry_t *re; - mib2_ipNetToMediaEntry_t ntme; mib2_ipAttributeEntry_t *iae, *iaeptr; ipaddr_t gw_addr; tsol_ire_gw_secattr_t *attrp; @@ -18857,11 +18854,6 @@ ip_snmp_get2_v4(ire_t *ire, iproutedata_t *ird) re->ipRouteInfo.re_max_frag = ire->ire_max_frag; re->ipRouteInfo.re_frag_flag = ire->ire_frag_flag; re->ipRouteInfo.re_rtt = ire->ire_uinfo.iulp_rtt; - if (ire->ire_nce && - ire->ire_nce->nce_state == ND_REACHABLE) - llmp = ire->ire_nce->nce_res_mp; - else - llmp = NULL; re->ipRouteInfo.re_ref = ire->ire_refcnt; re->ipRouteInfo.re_src_addr = ire->ire_src_addr; re->ipRouteInfo.re_obpkt = ire->ire_ob_pkt_count; @@ -18903,52 +18895,6 @@ ip_snmp_get2_v4(ire_t *ire, iproutedata_t *ird) (unsigned)(sacnt * sizeof (*iae)))); } - if (ire->ire_type != IRE_CACHE || gw_addr != 0) - goto done; - /* - * only IRE_CACHE entries that are for a directly connected subnet - * get appended to net -> phys addr table - * (others in arp) - */ - ntme.ipNetToMediaIfIndex.o_length = 0; - ill = ire_to_ill(ire); - ASSERT(ill != NULL); - ntme.ipNetToMediaIfIndex.o_length = - ill->ill_name_length == 0 ? 0 : - MIN(OCTET_LENGTH, ill->ill_name_length - 1); - bcopy(ill->ill_name, ntme.ipNetToMediaIfIndex.o_bytes, - ntme.ipNetToMediaIfIndex.o_length); - - ntme.ipNetToMediaPhysAddress.o_length = 0; - if (llmp) { - uchar_t *addr; - - dlup = (dl_unitdata_req_t *)llmp->b_rptr; - /* Remove sap from address */ - if (ill->ill_sap_length < 0) - addr = llmp->b_rptr + dlup->dl_dest_addr_offset; - else - addr = llmp->b_rptr + dlup->dl_dest_addr_offset + - ill->ill_sap_length; - - ntme.ipNetToMediaPhysAddress.o_length = - MIN(OCTET_LENGTH, ill->ill_phys_addr_length); - bcopy(addr, ntme.ipNetToMediaPhysAddress.o_bytes, - ntme.ipNetToMediaPhysAddress.o_length); - } - ntme.ipNetToMediaNetAddress = ire->ire_addr; - /* assume dynamic (may be changed in arp) */ - ntme.ipNetToMediaType = 3; - ntme.ipNetToMediaInfo.ntm_mask.o_length = sizeof (uint32_t); - bcopy(&ire->ire_mask, ntme.ipNetToMediaInfo.ntm_mask.o_bytes, - ntme.ipNetToMediaInfo.ntm_mask.o_length); - ntme.ipNetToMediaInfo.ntm_flags = ACE_F_RESOLVED; - if (!snmp_append_data2(ird->ird_netmedia.lp_head, - &ird->ird_netmedia.lp_tail, (char *)&ntme, sizeof (ntme))) { - ip1dbg(("ip_snmp_get2_v4: failed to allocate %u bytes\n", - (uint_t)sizeof (ntme))); - } -done: /* bump route index for next pass */ ird->ird_idx++; |