2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
30 * ATM interface management
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/sockio.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
44 #include <net/if_types.h>
45 #include <net/if_dl.h>
46 #include <net/route.h>
48 #include <netinet/in.h>
49 #include <netinet/in_var.h>
50 #include <netatm/port.h>
51 #include <netatm/queue.h>
52 #include <netatm/atm.h>
53 #include <netatm/atm_sys.h>
54 #include <netatm/atm_sap.h>
55 #include <netatm/atm_cm.h>
56 #include <netatm/atm_if.h>
57 #include <netatm/atm_ioctl.h>
58 #include <netatm/atm_sigmgr.h>
59 #include <netatm/atm_stack.h>
60 #include <netatm/atm_pcb.h>
61 #include <netatm/atm_var.h>
66 static int atm_physif_ioctl(int, caddr_t, caddr_t);
67 static int atm_if_ioctl(struct ifnet *, u_long, caddr_t);
68 static int atm_ifparse(const char *, char *, size_t, int *);
73 static int (*atm_ifouttbl[AF_MAX+1])
74 (struct ifnet *, KBuffer *, struct sockaddr *)
79 * Register an ATM physical interface
81 * Each ATM device interface must register itself here upon completing
82 * its internal initialization. This applies to both linked and loaded
83 * device drivers. The interface must be registered before a signalling
84 * manager can be attached.
87 * cup pointer to interface's common unit structure
88 * name pointer to device name string
89 * sdp pointer to interface's stack services
92 * 0 registration successful
93 * errno registration failed - reason indicated
97 atm_physif_register(cup, name, sdp)
100 struct stack_defn *sdp;
106 * See if we need to be initialized
112 * Make sure we're not already registered
114 if (cup->cu_flags & CUF_REGISTER) {
121 * Make sure an interface is only registered once
123 for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
124 if ((cup->cu_unit == pip->pif_unit) &&
125 (strcmp(name, pip->pif_name) == 0)) {
132 * Fill in physical interface parameters
135 pip->pif_name = name;
136 pip->pif_unit = cup->cu_unit;
137 pip->pif_flags = PIF_UP;
138 pip->pif_services = sdp;
139 pip->pif_ioctl = atm_physif_ioctl;
142 * Link in the interface and mark us registered
144 LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next);
145 cup->cu_flags |= CUF_REGISTER;
153 * De-register an ATM physical interface
155 * Each ATM interface must de-register itself before downing the interface.
156 * The interface's signalling manager will be detached and any network
157 * interface and VCC control blocks will be freed.
160 * cup pointer to interface's common unit structure
163 * 0 de-registration successful
164 * errno de-registration failed - reason indicated
168 atm_physif_deregister(cup)
171 struct atm_pif *pip = (struct atm_pif *)&cup->cu_pif;
177 * Detach and deregister, if needed
179 if ((cup->cu_flags & CUF_REGISTER)) {
182 * Detach from signalling manager
184 if (pip->pif_sigmgr != NULL) {
185 err = atm_sigmgr_detach(pip);
186 if (err && (err != ENOENT)) {
193 * Make sure signalling manager is detached
195 if (pip->pif_sigmgr != NULL) {
203 UNLINK(pip, struct atm_pif, atm_interface_head, pif_next);
205 cup->cu_flags &= ~CUF_REGISTER;
209 * Free all of our network interfaces
211 atm_physif_freenifs(pip, cup->cu_nif_zone);
214 * Free unit's vcc information
218 uma_zfree(cup->cu_vcc_zone, cvp);
221 cup->cu_vcc = (Cmn_vcc *)NULL;
230 * Free all network interfaces on a physical interface
233 * pip pointer to physical interface structure
240 atm_physif_freenifs(pip, zone)
244 struct atm_nif *nip = pip->pif_nif;
250 * atm_nif_detach zeros pointers - save so we can
253 struct atm_nif *nipp = nip->nif_pnext;
256 * Clean up network i/f trails
259 uma_zfree(zone, nip);
262 pip->pif_nif = (struct atm_nif *)NULL;
270 * Handle physical interface ioctl's
272 * See <netatm/atm_ioctl.h> for definitions.
277 * code Ioctl function (sub)code
278 * data Data block. On input contains command,
279 * on output, contains results
280 * arg Optional code specific arguments
283 * 0 Request processed successfully
284 * errno Request failed - reason code
288 atm_physif_ioctl(code, data, arg)
293 struct atminfreq *aip = (struct atminfreq *)data;
294 struct atmsetreq *asr = (struct atmsetreq *)data;
302 caddr_t buf = aip->air_buf_addr;
303 struct air_phy_stat_rsp *apsp;
304 struct air_int_rsp apr;
305 struct air_netif_rsp anr;
306 struct air_cfg_rsp acr;
309 size_t buf_len = aip->air_buf_len;
311 char ifname[2*IFNAMSIZ];
313 struct in_ifaddr *ia;
314 struct sockaddr_dl *sdl;
317 switch ( aip->air_opcode ) {
321 * Get physical interface information
323 aip = (struct atminfreq *)data;
324 pip = (struct atm_pif *)arg;
327 * Make sure there's room in user buffer
329 if (aip->air_buf_len < sizeof(apr)) {
335 * Fill in info to be returned
337 bzero((caddr_t)&apr, sizeof(apr));
338 smp = pip->pif_sigmgr;
339 sip = pip->pif_siginst;
340 (void) snprintf(apr.anp_intf, sizeof(apr.anp_intf),
341 "%s%d", pip->pif_name, pip->pif_unit );
344 strcpy(apr.anp_nif_pref, pip->pif_nif->nif_ifp->if_dname);
349 nip = nip->nif_pnext;
353 ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr);
354 ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr);
355 apr.anp_sig_proto = smp->sm_proto;
356 apr.anp_sig_state = sip->si_state;
360 * Copy data to user buffer
362 err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr));
367 * Update buffer pointer/count
369 aip->air_buf_addr += sizeof(apr);
370 aip->air_buf_len -= sizeof(apr);
375 * Get network interface information
377 aip = (struct atminfreq *)data;
378 nip = (struct atm_nif *)arg;
383 * Make sure there's room in user buffer
385 if (aip->air_buf_len < sizeof(anr)) {
391 * Fill in info to be returned
393 bzero((caddr_t)&anr, sizeof(anr));
394 (void) snprintf(anr.anp_intf, sizeof(anr.anp_intf),
395 "%s%d", ifp->if_dname, ifp->if_dunit);
398 anr.anp_proto_addr = *ia->ia_ifa.ifa_addr;
400 (void) snprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf),
401 "%s%d", pip->pif_name, pip->pif_unit);
404 * Copy data to user buffer
406 err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr));
411 * Update buffer pointer/count
413 aip->air_buf_addr += sizeof(anr);
414 aip->air_buf_len -= sizeof(anr);
419 * Get per interface statistics
421 pip = (struct atm_pif *)arg;
424 snprintf ( ifname, sizeof(ifname),
425 "%s%d", pip->pif_name, pip->pif_unit );
428 * Cast response into users buffer
430 apsp = (struct air_phy_stat_rsp *)buf;
435 len = sizeof ( struct air_phy_stat_rsp );
440 * Copy interface name into response
442 if ((err = copyout ( ifname, apsp->app_intf, IFNAMSIZ)) != 0)
448 if ((err = copyout(&pip->pif_ipdus, &apsp->app_ipdus,
449 len - sizeof(apsp->app_intf))) != 0)
453 * Adjust buffer elements
458 aip->air_buf_addr = buf;
459 aip->air_buf_len = buf_len;
464 * Set NIF - allow user to configure 1 or more logical
465 * interfaces per physical interface.
469 * Get pointer to physical interface structure from
472 pip = (struct atm_pif *)arg;
473 cup = (Cmn_unit *)pip;
476 * Sanity check - are we already connected to something?
478 if ( pip->pif_sigmgr )
485 * Free any previously allocated NIFs
487 atm_physif_freenifs(pip, cup->cu_nif_zone);
490 * Add list of interfaces
492 for ( count = 0; count < asr->asr_nif_cnt; count++ )
494 nip = uma_zalloc(cup->cu_nif_zone, M_WAITOK | M_ZERO);
498 * Destroy any successful nifs
500 atm_physif_freenifs(pip, cup->cu_nif_zone);
506 ifp = nip->nif_ifp = if_alloc(IFT_IPOVERATM);
508 uma_zfree(cup->cu_nif_zone, nip);
510 * Destroy any successful nifs
512 atm_physif_freenifs(pip, cup->cu_nif_zone);
516 strcpy ( nip->nif_name, asr->asr_nif_pref );
517 nip->nif_sel = count;
519 if_initname(ifp, nip->nif_name, count);
520 ifp->if_mtu = ATM_NIF_MTU;
521 ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
522 ifp->if_output = atm_ifoutput;
523 ifp->if_ioctl = atm_if_ioctl;
524 ifp->if_snd.ifq_maxlen = ifqmaxlen;
525 switch ( cup->cu_config.ac_media ) {
527 ifp->if_baudrate = 100000000;
530 ifp->if_baudrate = 140000000;
535 ifp->if_baudrate = 155000000;
538 ifp->if_baudrate = 25600000;
541 ifp->if_baudrate = 100000000; /* XXX */
544 ifp->if_baudrate = 2500000; /* XXX */
547 ifp->if_baudrate = 9600;
550 if ((err = atm_nif_attach(nip)) != 0) {
551 if_free(nip->nif_ifp);
552 uma_zfree(cup->cu_nif_zone, nip);
554 * Destroy any successful nifs
556 atm_physif_freenifs(pip, cup->cu_nif_zone);
560 * Set macaddr in <Link> address
563 ifa = ifaddr_byindex(ifp->if_index);
565 sdl = (struct sockaddr_dl *)
567 sdl->sdl_type = IFT_ETHER;
568 sdl->sdl_alen = ifp->if_addrlen;
569 bcopy ( (caddr_t)&cup->cu_config.ac_macaddr,
570 LLADDR(sdl), ifp->if_addrlen );
577 * Get adapter configuration information
579 aip = (struct atminfreq *)data;
580 pip = (struct atm_pif *)arg;
581 cup = (Cmn_unit *)pip;
582 acp = &cup->cu_config;
585 * Make sure there's room in user buffer
587 if (aip->air_buf_len < sizeof(acr)) {
593 * Fill in info to be returned
595 bzero((caddr_t)&acr, sizeof(acr));
596 (void) snprintf(acr.acp_intf, sizeof(acr.acp_intf),
597 "%s%d", pip->pif_name, pip->pif_unit);
598 bcopy((caddr_t)acp, (caddr_t)&acr.acp_cfg,
602 * Copy data to user buffer
604 err = copyout((caddr_t)&acr, aip->air_buf_addr,
610 * Update buffer pointer/count
612 aip->air_buf_addr += sizeof(acr);
613 aip->air_buf_len -= sizeof(acr);
618 * Pass off to device-specific handler
620 cup = (Cmn_unit *)arg;
624 err = (*cup->cu_ioctl)(code, data, arg);
636 * Register a Network Convergence Module
638 * Each ATM network convergence module must register itself here before
639 * it will receive network interface status notifications.
642 * ncp pointer to network convergence definition structure
645 * 0 registration successful
646 * errno registration failed - reason indicated
650 atm_netconv_register(ncp)
657 * See if we need to be initialized
663 * Validate protocol family
665 if (ncp->ncm_family > AF_MAX) {
671 * Ensure no duplicates
673 for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) {
674 if (tdp->ncm_family == ncp->ncm_family) {
683 LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next);
686 * Add new interface output function
688 atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput;
696 * De-register an ATM Network Convergence Module
698 * Each ATM network convergence provider must de-register its registered
699 * service(s) before terminating. Specifically, loaded kernel modules
700 * must de-register their services before unloading themselves.
703 * ncp pointer to network convergence definition structure
706 * 0 de-registration successful
707 * errno de-registration failed - reason indicated
711 atm_netconv_deregister(ncp)
714 int found, s = splnet();
717 * Remove module from list
719 UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found);
727 * Remove module's interface output function
729 atm_ifouttbl[ncp->ncm_family] = NULL;
737 * Attach an ATM Network Interface
739 * Before an ATM network interface can be used by the system, the owning
740 * device interface must attach the network interface using this function.
741 * The physical interface for this network interface must have been previously
742 * registered (using atm_interface_register). The network interface will be
743 * added to the kernel's interface list and to the physical interface's list.
744 * The caller is responsible for initializing the control block fields.
747 * nip pointer to atm network interface control block
750 * 0 attach successful
751 * errno attach failed - reason indicated
758 struct atm_pif *pip, *pip2;
771 * Verify physical interface is registered
773 for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) {
777 if ((pip == NULL) || (pip2 == NULL)) {
783 * Add to system interface list
788 * Add to BPF interface list
789 * DLT_ATM_RFC_1483 cannot be used because both NULL and LLC/SNAP could
792 bpfattach(ifp, DLT_ATM_CLIP, T_ATM_LLC_MAX_LEN);
795 * Add to physical interface list
797 LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext);
800 * Notify network convergence modules of new network i/f
802 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
805 err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0);
819 * Detach an ATM Network Interface
821 * Before an ATM network interface control block can be freed, all kernel
822 * references to/from this block must be released. This function will delete
823 * all routing references to the interface and free all interface addresses
824 * for the interface. The network interface will then be removed from the
825 * kernel's interface list and from the owning physical interface's list.
826 * The caller is responsible for free'ing the control block.
829 * nip pointer to atm network interface control block
841 struct ifnet *ifp = nip->nif_ifp;
846 * Notify convergence modules of network i/f demise
848 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
849 (void) (*ncp->ncm_stat)(NCM_DETACH, nip, 0);
853 * Remove from BPF interface list
858 * Free all interface routes and addresses,
859 * delete all remaining routes using this interface,
860 * then remove from the system interface list
866 * Remove from physical interface list
868 UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext);
874 * Set an ATM Network Interface address
876 * This is called from a device interface when processing an SIOCSIFADDR
877 * ioctl request. We just notify all convergence modules of the new address
878 * and hope everyone has non-overlapping interests, since if someone reports
879 * an error we don't go back and tell everyone to undo the change.
882 * nip pointer to atm network interface control block
883 * ifa pointer to new interface address
887 * errno set failed - reason indicated
891 atm_nif_setaddr(nip, ifa)
896 int err = 0, s = splnet();
899 * Notify convergence modules of network i/f change
901 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
902 err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (intptr_t)ifa);
913 * ATM Interface Packet Output
915 * All ATM network interfaces must have their ifnet if_output address set to
916 * this function. Since no existing network layer code is to be modified
917 * for ATM support, this function serves as the hook to allow network output
918 * packets to be assigned to their proper outbound VCC. Each network address
919 * family which is to be supported over ATM must be assigned an output
920 * packet processing function via atm_netconv_register().
923 * ifp pointer to ifnet structure
924 * m pointer to packet buffer chain to be output
925 * dst pointer to packet's network destination address
928 * 0 packet queued to interface
929 * errno output failed - reason indicated
933 atm_ifoutput(ifp, m, dst, rt)
936 struct sockaddr *dst;
939 u_short fam = dst->sa_family;
940 int (*func)(struct ifnet *, KBuffer *,
944 * Validate address family
948 return (EAFNOSUPPORT);
952 * Hand packet off for dst-to-VCC mapping
954 func = atm_ifouttbl[fam];
957 return (EAFNOSUPPORT);
959 return ((*func)(ifp, m, dst));
964 * Handle interface ioctl requests.
967 * ifp pointer to network interface structure
969 * data arguments to/from ioctl
975 atm_if_ioctl(ifp, cmd, data)
980 register struct ifreq *ifr = (struct ifreq *)data;
981 struct atm_nif *nip = IFP2ANIF(ifp);
988 bcopy ( (caddr_t)&(nip->nif_pif->pif_macaddr),
989 (caddr_t)ifr->ifr_addr.sa_data,
990 sizeof(struct mac_addr) );
994 error = atm_nif_setaddr ( nip, (struct ifaddr *)data);
995 ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST;
999 *(int *)data = ifp->if_flags;
1016 * Parse interface name
1018 * Parses an interface name string into a name and a unit component.
1021 * name pointer to interface name string
1022 * namep address to store interface name
1023 * size size available at namep
1024 * unitp address to store interface unit number
1032 atm_ifparse(const char *name, char *namep, size_t size, int *unitp)
1040 * Separate supplied string into name and unit parts.
1045 if (*cp >= '0' && *cp <= '9')
1052 while (*cp && *cp >= '0' && *cp <= '9')
1053 unit = 10 * unit + *cp++ - '0';
1062 * Locate ATM physical interface via name
1064 * Uses the supplied interface name string to locate a registered
1065 * ATM physical interface.
1068 * name pointer to interface name string
1071 * 0 interface not found
1072 * else pointer to atm physical interface structure
1079 struct atm_pif *pip;
1086 if (atm_ifparse(name, n, sizeof(n), &unit))
1087 return ((struct atm_pif *)0);
1090 * Look for the physical interface
1092 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1093 if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0))
1102 * Locate ATM network interface via name
1104 * Uses the supplied interface name string to locate an ATM network interface.
1107 * name pointer to interface name string
1110 * 0 interface not found
1111 * else pointer to atm network interface structure
1118 struct atm_pif *pip;
1119 struct atm_nif *nip;
1126 if (atm_ifparse(name, n, sizeof(n), &unit))
1127 return ((struct atm_nif *)0);
1130 * Search thru each physical interface
1132 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1134 * Looking for network interface
1136 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
1137 struct ifnet *ifp = (struct ifnet *)nip;
1138 if ((ifp->if_dunit == unit) &&
1139 (strcmp(ifp->if_dname, n) == 0))