3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/atm_if.c,v 1.5 1999/08/28 00:48:35 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/atm_if.c,v 1.7 2004/04/01 07:27:17 joerg Exp $
34 * ATM interface management
38 #include "kern_include.h"
40 #if (defined(BSD) && (BSD < 199506))
47 static int atm_physif_ioctl (int, caddr_t, caddr_t);
48 #if (defined(BSD) && (BSD >= 199306))
49 static int atm_netif_rtdel (struct radix_node *, void *);
51 static int atm_if_ioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
52 static int atm_ifparse (char *, char *, int, int *);
57 static int (*atm_ifouttbl[AF_MAX+1])
58 (struct ifnet *, KBuffer *, struct sockaddr *)
63 * Register an ATM physical interface
65 * Each ATM device interface must register itself here upon completing
66 * its internal initialization. This applies to both linked and loaded
67 * device drivers. The interface must be registered before a signalling
68 * manager can be attached.
71 * cup pointer to interface's common unit structure
72 * name pointer to device name string
73 * sdp pointer to interface's stack services
76 * 0 registration successful
77 * errno registration failed - reason indicated
81 atm_physif_register(cup, name, sdp)
84 struct stack_defn *sdp;
90 * See if we need to be initialized
96 * Make sure we're not already registered
98 if (cup->cu_flags & CUF_REGISTER) {
105 * Make sure an interface is only registered once
107 for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
108 if ((cup->cu_unit == pip->pif_unit) &&
109 (strcmp(name, pip->pif_name) == 0)) {
116 * Fill in physical interface parameters
119 pip->pif_name = name;
120 pip->pif_unit = cup->cu_unit;
121 pip->pif_flags = PIF_UP;
122 pip->pif_services = sdp;
123 pip->pif_ioctl = atm_physif_ioctl;
126 * Link in the interface and mark us registered
128 LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next);
129 cup->cu_flags |= CUF_REGISTER;
137 * De-register an ATM physical interface
139 * Each ATM interface must de-register itself before downing the interface.
140 * The interface's signalling manager will be detached and any network
141 * interface and VCC control blocks will be freed.
144 * cup pointer to interface's common unit structure
147 * 0 de-registration successful
148 * errno de-registration failed - reason indicated
152 atm_physif_deregister(cup)
155 struct atm_pif *pip = (struct atm_pif *)&cup->cu_pif;
161 * Detach and deregister, if needed
163 if ((cup->cu_flags & CUF_REGISTER)) {
166 * Detach from signalling manager
168 if (pip->pif_sigmgr != NULL) {
169 err = atm_sigmgr_detach(pip);
170 if (err && (err != ENOENT)) {
177 * Make sure signalling manager is detached
179 if (pip->pif_sigmgr != NULL) {
187 UNLINK(pip, struct atm_pif, atm_interface_head, pif_next);
189 cup->cu_flags &= ~CUF_REGISTER;
193 * Free all of our network interfaces
195 atm_physif_freenifs(pip);
198 * Free unit's vcc information
205 cup->cu_vcc = (Cmn_vcc *)NULL;
214 * Free all network interfaces on a physical interface
217 * pip pointer to physical interface structure
224 atm_physif_freenifs(pip)
227 struct atm_nif *nip = pip->pif_nif;
233 * atm_nif_detach zeros pointers - save so we can
236 struct atm_nif *nipp = nip->nif_pnext;
239 * Clean up network i/f trails
241 atm_nif_detach ( nip );
242 atm_free ((caddr_t)nip);
245 pip->pif_nif = (struct atm_nif *)NULL;
254 * Handle physical interface ioctl's
256 * See <netatm/atm_ioctl.h> for definitions.
261 * code Ioctl function (sub)code
262 * data Data block. On input contains command,
263 * on output, contains results
264 * arg Optional code specific arguments
267 * 0 Request processed successfully
268 * errno Request failed - reason code
272 atm_physif_ioctl(code, data, arg)
277 struct atminfreq *aip = (struct atminfreq *)data;
278 struct atmsetreq *asr = (struct atmsetreq *)data;
286 caddr_t buf = aip->air_buf_addr;
287 struct air_phy_stat_rsp *apsp;
288 struct air_int_rsp apr;
289 struct air_netif_rsp anr;
290 struct air_cfg_rsp acr;
291 int count, len, buf_len = aip->air_buf_len;
293 char ifname[2*IFNAMSIZ];
294 #if (defined(BSD) && (BSD >= 199103))
296 struct in_ifaddr *ia;
297 struct sockaddr_dl *sdl;
301 switch ( aip->air_opcode ) {
305 * Get physical interface information
307 aip = (struct atminfreq *)data;
308 pip = (struct atm_pif *)arg;
311 * Make sure there's room in user buffer
313 if (aip->air_buf_len < sizeof(apr)) {
319 * Fill in info to be returned
321 KM_ZERO((caddr_t)&apr, sizeof(apr));
322 smp = pip->pif_sigmgr;
323 sip = pip->pif_siginst;
324 (void) snprintf(apr.anp_intf, sizeof(apr.anp_intf),
325 "%s%d", pip->pif_name, pip->pif_unit );
328 strcpy(apr.anp_nif_pref, /* XXX: strings */
329 pip->pif_nif->nif_if.if_dname);
334 nip = nip->nif_pnext;
338 ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr);
339 ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr);
340 apr.anp_sig_proto = smp->sm_proto;
341 apr.anp_sig_state = sip->si_state;
345 * Copy data to user buffer
347 err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr));
352 * Update buffer pointer/count
354 aip->air_buf_addr += sizeof(apr);
355 aip->air_buf_len -= sizeof(apr);
360 * Get network interface information
362 aip = (struct atminfreq *)data;
363 nip = (struct atm_nif *)arg;
368 * Make sure there's room in user buffer
370 if (aip->air_buf_len < sizeof(anr)) {
376 * Fill in info to be returned
378 KM_ZERO((caddr_t)&anr, sizeof(anr));
379 (void) snprintf(anr.anp_intf, sizeof(anr.anp_intf),
380 "%s", ifp->if_xname);
383 anr.anp_proto_addr = *ia->ia_ifa.ifa_addr;
385 (void) snprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf),
386 "%s%d", pip->pif_name, pip->pif_unit);
389 * Copy data to user buffer
391 err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr));
396 * Update buffer pointer/count
398 aip->air_buf_addr += sizeof(anr);
399 aip->air_buf_len -= sizeof(anr);
404 * Get per interface statistics
406 pip = (struct atm_pif *)arg;
409 snprintf ( ifname, sizeof(ifname),
410 "%s%d", pip->pif_name, pip->pif_unit );
413 * Cast response into users buffer
415 apsp = (struct air_phy_stat_rsp *)buf;
420 len = sizeof ( struct air_phy_stat_rsp );
425 * Copy interface name into response
427 if ((err = copyout ( ifname, apsp->app_intf, IFNAMSIZ)) != 0)
433 if ((err = copyout(&pip->pif_ipdus, &apsp->app_ipdus,
434 len - sizeof(apsp->app_intf))) != 0)
438 * Adjust buffer elements
443 aip->air_buf_addr = buf;
444 aip->air_buf_len = buf_len;
449 * Set NIF - allow user to configure 1 or more logical
450 * interfaces per physical interface.
454 * Get pointer to physical interface structure from
457 pip = (struct atm_pif *)arg;
458 cup = (Cmn_unit *)pip;
461 * Sanity check - are we already connected to something?
463 if ( pip->pif_sigmgr )
470 * Free any previously allocated NIFs
472 atm_physif_freenifs(pip);
475 * Add list of interfaces
477 for ( count = 0; count < asr->asr_nif_cnt; count++ )
479 nip = (struct atm_nif *)atm_allocate(cup->cu_nif_pool);
483 * Destroy any successful nifs
485 atm_physif_freenifs(pip);
493 strcpy ( nip->nif_name, asr->asr_nif_pref );
494 nip->nif_sel = count;
496 if_initname(ifp, nip->nif_name, count);
497 ifp->if_mtu = ATM_NIF_MTU;
498 ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
499 ifp->if_output = atm_ifoutput;
500 ifp->if_ioctl = atm_if_ioctl;
501 ifp->if_snd.ifq_maxlen = ifqmaxlen;
502 #if (defined(BSD) && (BSD >= 199103))
504 * Set if_type and if_baudrate
506 ifp->if_type = IFT_ATM;
507 switch ( cup->cu_config.ac_media ) {
509 ifp->if_baudrate = 100000000;
512 ifp->if_baudrate = 140000000;
517 ifp->if_baudrate = 155000000;
520 panic("AIOCF_SETNIF: unknown media");
524 if ((err = atm_nif_attach(nip)) != 0) {
525 atm_free ( (caddr_t)nip );
528 * Destroy any successful nifs
530 atm_physif_freenifs(pip);
533 #if (defined(BSD) && (BSD >= 199103))
535 * Set macaddr in <Link> address
538 ifa = ifnet_addrs[ifp->if_index - 1];
540 sdl = (struct sockaddr_dl *)
542 sdl->sdl_type = IFT_ETHER;
543 sdl->sdl_alen = ifp->if_addrlen;
544 bcopy ( (caddr_t)&cup->cu_config.ac_macaddr,
545 LLADDR(sdl), ifp->if_addrlen );
553 * Get adapter configuration information
555 aip = (struct atminfreq *)data;
556 pip = (struct atm_pif *)arg;
557 cup = (Cmn_unit *)pip;
558 acp = &cup->cu_config;
561 * Make sure there's room in user buffer
563 if (aip->air_buf_len < sizeof(acr)) {
569 * Fill in info to be returned
571 KM_ZERO((caddr_t)&acr, sizeof(acr));
572 (void) snprintf(acr.acp_intf, sizeof(acr.acp_intf),
573 "%s%d", pip->pif_name, pip->pif_unit);
574 KM_COPY((caddr_t)acp, (caddr_t)&acr.acp_cfg,
578 * Copy data to user buffer
580 err = copyout((caddr_t)&acr, aip->air_buf_addr,
586 * Update buffer pointer/count
588 aip->air_buf_addr += sizeof(acr);
589 aip->air_buf_len -= sizeof(acr);
594 * Pass off to device-specific handler
596 cup = (Cmn_unit *)arg;
600 err = (*cup->cu_ioctl)(code, data, arg);
612 * Register a Network Convergence Module
614 * Each ATM network convergence module must register itself here before
615 * it will receive network interface status notifications.
618 * ncp pointer to network convergence definition structure
621 * 0 registration successful
622 * errno registration failed - reason indicated
626 atm_netconv_register(ncp)
633 * See if we need to be initialized
639 * Validate protocol family
641 if (ncp->ncm_family > AF_MAX) {
647 * Ensure no duplicates
649 for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) {
650 if (tdp->ncm_family == ncp->ncm_family) {
659 LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next);
662 * Add new interface output function
664 atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput;
672 * De-register an ATM Network Convergence Module
674 * Each ATM network convergence provider must de-register its registered
675 * service(s) before terminating. Specifically, loaded kernel modules
676 * must de-register their services before unloading themselves.
679 * ncp pointer to network convergence definition structure
682 * 0 de-registration successful
683 * errno de-registration failed - reason indicated
687 atm_netconv_deregister(ncp)
690 int found, s = splnet();
693 * Remove module from list
695 UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found);
703 * Remove module's interface output function
705 atm_ifouttbl[ncp->ncm_family] = NULL;
713 * Attach an ATM Network Interface
715 * Before an ATM network interface can be used by the system, the owning
716 * device interface must attach the network interface using this function.
717 * The physical interface for this network interface must have been previously
718 * registered (using atm_interface_register). The network interface will be
719 * added to the kernel's interface list and to the physical interface's list.
720 * The caller is responsible for initializing the control block fields.
723 * nip pointer to atm network interface control block
726 * 0 attach successful
727 * errno attach failed - reason indicated
734 struct atm_pif *pip, *pip2;
745 * Verify physical interface is registered
747 for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) {
751 if ((pip == NULL) || (pip2 == NULL)) {
757 * Add to system interface list
762 * Add to physical interface list
764 LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext);
767 * Notify network convergence modules of new network i/f
769 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
772 err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0);
786 * Detach an ATM Network Interface
788 * Before an ATM network interface control block can be freed, all kernel
789 * references to/from this block must be released. This function will delete
790 * all routing references to the interface and free all interface addresses
791 * for the interface. The network interface will then be removed from the
792 * kernel's interface list and from the owning physical interface's list.
793 * The caller is responsible for free'ing the control block.
796 * nip pointer to atm network interface control block
808 struct ifnet *ifp = &nip->nif_if;
810 struct in_ifaddr *ia;
811 struct radix_node_head *rnh;
817 * Notify convergence modules of network i/f demise
819 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
820 (void) (*ncp->ncm_stat)(NCM_DETACH, nip, 0);
824 * Mark interface down
829 * Free all interface routes and addresses
836 /* Delete interface route */
839 /* Remove interface address from queues */
841 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
842 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
844 /* Free interface address */
849 * Delete all remaining routes using this interface
850 * Unfortuneatly the only way to do this is to slog through
851 * the entire routing table looking for routes which point
852 * to this interface...oh well...
854 for (i = 1; i <= AF_MAX; i++) {
855 if ((rnh = rt_tables[i]) == NULL)
857 (void) rnh->rnh_walktree(rnh, atm_netif_rtdel, ifp);
861 * Remove from system interface list (ie. if_detach())
863 TAILQ_REMOVE(&ifnet, ifp, if_link);
866 * Remove from physical interface list
868 UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext);
875 * Delete Routes for a Network Interface
877 * Called for each routing entry via the rnh->rnh_walktree() call above
878 * to delete all route entries referencing a detaching network interface.
881 * rn pointer to node in the routing table
882 * arg argument passed to rnh->rnh_walktree() - detaching interface
886 * errno failed - reason indicated
890 atm_netif_rtdel(rn, arg)
891 struct radix_node *rn;
894 struct rtentry *rt = (struct rtentry *)rn;
895 struct ifnet *ifp = arg;
898 if (rt->rt_ifp == ifp) {
901 * Protect (sorta) against walktree recursion problems
904 if ((rt->rt_flags & RTF_UP) == 0)
907 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
908 rt_mask(rt), rt->rt_flags,
909 (struct rtentry **) NULL);
911 log(LOG_WARNING, "atm_netif_rtdel: error %d\n", err);
920 * Set an ATM Network Interface address
922 * This is called from a device interface when processing an SIOCSIFADDR
923 * ioctl request. We just notify all convergence modules of the new address
924 * and hope everyone has non-overlapping interests, since if someone reports
925 * an error we don't go back and tell everyone to undo the change.
928 * nip pointer to atm network interface control block
929 * ifa pointer to new interface address
933 * errno set failed - reason indicated
937 atm_nif_setaddr(nip, ifa)
942 int err = 0, s = splnet();
945 * Notify convergence modules of network i/f change
947 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
948 err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (int)ifa);
959 * ATM Interface Packet Output
961 * All ATM network interfaces must have their ifnet if_output address set to
962 * this function. Since no existing network layer code is to be modified
963 * for ATM support, this function serves as the hook to allow network output
964 * packets to be assigned to their proper outbound VCC. Each network address
965 * family which is to be supported over ATM must be assigned an output
966 * packet processing function via atm_netconv_register().
969 * ifp pointer to ifnet structure
970 * m pointer to packet buffer chain to be output
971 * dst pointer to packet's network destination address
974 * 0 packet queued to interface
975 * errno output failed - reason indicated
979 #if (defined(BSD) && (BSD >= 199103))
980 atm_ifoutput(ifp, m, dst, rt)
982 atm_ifoutput(ifp, m, dst)
986 struct sockaddr *dst;
987 #if (defined(BSD) && (BSD >= 199103))
991 u_short fam = dst->sa_family;
992 int (*func)(struct ifnet *, KBuffer *,
996 * Validate address family
1000 return (EAFNOSUPPORT);
1004 * Hand packet off for dst-to-VCC mapping
1006 func = atm_ifouttbl[fam];
1009 return (EAFNOSUPPORT);
1011 return ((*func)(ifp, m, dst));
1016 * Handle interface ioctl requests.
1019 * ifp pointer to network interface structure
1021 * data arguments to/from ioctl
1027 atm_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
1029 register struct ifreq *ifr = (struct ifreq *)data;
1030 struct atm_nif *nip = (struct atm_nif *)ifp;
1037 KM_COPY ( (caddr_t)&(nip->nif_pif->pif_macaddr),
1038 (caddr_t)ifr->ifr_addr.sa_data,
1039 sizeof(struct mac_addr) );
1043 error = atm_nif_setaddr ( nip, (struct ifaddr *)data);
1044 ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST;
1048 *(short *)data = ifp->if_flags;
1065 * Parse interface name
1067 * Parses an interface name string into a name and a unit component.
1070 * name pointer to interface name string
1071 * namep address to store interface name
1072 * size size available at namep
1073 * unitp address to store interface unit number
1081 atm_ifparse(name, namep, size, unitp)
1088 int len = 0, unit = 0;
1091 * Separate supplied string into name and unit parts.
1096 if (*cp >= '0' && *cp <= '9')
1103 while (*cp && *cp >= '0' && *cp <= '9')
1104 unit = 10 * unit + *cp++ - '0';
1113 * Locate ATM physical interface via name
1115 * Uses the supplied interface name string to locate a registered
1116 * ATM physical interface.
1119 * name pointer to interface name string
1122 * 0 interface not found
1123 * else pointer to atm physical interface structure
1130 struct atm_pif *pip;
1137 if (atm_ifparse(name, n, sizeof(n), &unit))
1138 return ((struct atm_pif *)0);
1141 * Look for the physical interface
1143 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1144 if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0))
1153 * Locate ATM network interface via name
1155 * Uses the supplied interface name string to locate an ATM network interface.
1158 * name pointer to interface name string
1161 * 0 interface not found
1162 * else pointer to atm network interface structure
1169 struct atm_pif *pip;
1170 struct atm_nif *nip;
1177 if (atm_ifparse(name, n, sizeof(n), &unit))
1178 return ((struct atm_nif *)0);
1181 * Search thru each physical interface
1183 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1185 * Looking for network interface
1187 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
1188 struct ifnet *ifp = (struct ifnet *)nip;
1189 if ((ifp->if_dunit == unit) &&
1190 (strcmp(ifp->if_dname, n) == 0))