---
title: WWDC2004 Session 102
framework: wwdc
role: article
path: wwdc/wwdc2004-102
---

# WWDC2004 Session 102

## Transcript

Kind: captions Language: en hello I'm here to talk about network kernel extensions on tiger as you probably already heard we've made a number of massive changes to the networking stack we had a few goals we were we've got we needed to get better SMP scalability we've been chipping dual-processor machines for a long time and the way that the locking model is set up in the kernel in panther and previous releases really didn't give us an ability to take full advantage of those multiple processors in addition we wanted to add support for 64-bit userspace processes and these changes required in order to implement this we needed to make a lot of changes to data structures and moving up functions around and it really led to just massive changes almost everywhere which broke kernel extensions the previous network kernel extensions so if you have a network crim o extension today that's floating on Panther it won't load on tiger if you use if you're just an IO kit driver and ethernet driver or something you'll be okay but if you've been using the old dl IL layer or socket filters protocol filters any of that stuff you're going to need to make changes to your nke to get it to work on tiger some of these changes involves moving to using opaque data structures and XS or functions we provide colonel programming interfaces which are well-defined set of interfaces for interacting with these data structures and the stack the initial implementation of those KPIs is available in the WWDC build that's on your CD there are actually some bugs in the kernel on that that will lead to a panic in a few situations so along with the previous session session 103 there's some content that's available online and part of that is a new kernel that you can use when you're trying to test these colonel programming interfaces so I encourage you to go ahead and download that and install that there's a reading you that explains how to get it installed and that'll let you play around with what I'm about to show you so we're going to go over the colonel programming interfaces yeah these are available on tiger these should give us more stability so that when we make changes in the future we aren't going to keep breaking your kernel extensions and moving over to the colonel programming interfaces is required to get your text running on tiger many of the symbols that use the link against are no longer there so with a better SMP scalability as I said we've been shipping this dual processor machines for a long time and we've been using this thing called a funnel the network funnel to protect all of the data structures inside the kernel and it's basically one big lock we've taken that one big lock and we've moved to finer grained locking where we use a bunch of blocking primitives such as the simple lock a mutex and multiple reader single rider locks and we've really broken it down so that we can have multiple processors running through the stack at the same time one of the results of this is that the kernel extensions are responsible for protecting their own data since there's no longer one big lock that goes the stack and the kernel extensions are running under they have to be aware that they could be re-entered the internal locking model that we use is mostly transparent to the n que es and that was done intentionally so that we will be able to make changes to that in the future as we tune the performance so in Panther we have one big lock around networking and we have another big lock around the file system and in tiger so the networking stack removed to a bunch of smaller lock in various areas and we're going to continue to fine-tune the exact locking model and the KPIs are intended to keep that transparent so that you don't have to be involved with it and we won't break you if we change it we did change the data structures in a lot of ways in order to implement this adding locks to these structures and moving stuff around adding reference count his did affect the binary compatibility we're going to have all criminal private data structures be opaque and we're going to provide accessor functions so that in the future when we need to make additional changes to these it won't cause problems we won't have to bake your text you won't have to recompile you want it to deal with any of that there are five main network KPIs there's the network interface KPI for providing new interfaces to the networking stack there's the socket KPI for interacting with sockets in the stack and inside the colonel this is commonly used for network file system such as NFS AFP and SMB we also have the socket filter KPI for filtering data and connections at the socket layer in addition is the IP filter which lets you filter IP packets at the IP layer regardless of the interface and finally we have the network interface filter which gives you an ability to filter packets at the interface layer there are a number of additional help or KPIs for getting access to various things such as I'm buffs or communicating with a user Damon in user space yeah so you have a diagram of the networking stack here and at the top layer we have the sockets the items in blue can be provided by kernel extensions so the kernel extensions can interact with the socket they can create a socket filter they can create an IP filter they can create what we call plumbers which I'll go into a little bit later as well as interfaces and interface filters so the network interface layer it's actually broken up into two different sections or two different layers there's the interface layer which has the interface itself such as an ethernet interface or a PPP interface and then there's the plumber layer and the plumber is the glue between a specific protocols such as IP and an interface such as ethernet so ideally the interface such as ethernet would know nothing about the protocol and the protocol shouldn't know anything about the interface it's the plumbers responsibility to tie these two things together if you're familiar with the datalink interface layer one of the things we've done is eliminate the interface family modules we found that a lot of the functionality that was provided by the interface family module was already was usually tied to the interface so we just went ahead and rolled all that functionality into the interface which makes it a lot easier to provide a new interface because instead of having to write an interface and an interface family module you just do it all in the interface we've also eliminated DL tags so when you're sending or receiving you'll the package what used to be a dl tag is now identified by both the interface and the protocol family so at the bottom of the stack we have network interfaces and the network interface kpi gives you the ability to provide new interfaces to the networking stack a network interface has five primary responsibilities network interface is responsible for inputting packets into the stack as well as d muxing the packets or determining which protocol a specific packet belongs to as part of the B MUX that has to handle add and delete protocols so that it can keep track of the D MUX descriptor mapping to protocol family mapping so it can match packets when they come in the interface is also responsible for framing the outbound packets basically putting an interface header on it as well as outputting the actual packet and handling.i octal for things when for cases where multicast filterless changes or other state changes are requested the network interface is documented in net / KPI underscore interface by H in the kernel framework network interfaces go through a typical lifecycle the network interface is allocated and then various parameters and properties of that interfacer set once the interface is set up correctly the interface is attached to the networking stack at that point the protocols attached and then packets are sent and received and then the the interface can request a detach the protocols detached from the interface and then the interface itself is detached from the stack for the allocated interface there's a I F net allocate function and you fill out an if' net in its parameter a pram structure that defines most of the initial parameters of the interface part of that is a unique ID and an interface family right now the networking stack keeps pointers to the network interface all over the place and it doesn't properly rest count rush count its references to the interface so we can't just get rid of the interface when your interface goes away we end up recycling it in the future we hope to get rid of this but for now we're kind of stuck with there are some little gotchas though with this when you're allocating an interface and you specify a unique ID and an interface family there must not be another interface that's currently attached with that unique ID and interface family if there is an interface and it's detaching then you may block until that detach is completed so that we can recycle to use the same interface again the recycle mechanism is temporary and we provide an if' net reference and is net relief for handling the reference counting for now when I have net release reaches zero the interface gets recycled in the future we will free it after you've allocated the interface you can set additional properties once you've set up the interface the way that you want it you can use I F net attached to attach the interface to the networking stack you can also specify a link layer address that will just be associated with that interface at this point the interface now appears in ifconfig and a kernel event gets genesis generated to notify the stack and people in user space or processes in user space that a new interface is attached and that made sugar protocols to attach the protocol touch is usually triggered from user space in response to a kernel event that an interface has been attached the plumber code is responsible for handling the attached it's plum function gets called to attach the protocol to the interface which in turn triggers the interfaces add protocol function the interfaces add protocol function gets passed a list of lists of G MUX descriptors and those DMX descriptors then map to a specific protocol family it's the interfaces responsibility to keep track track of those mappings so that when the demo Winnie interfaces d MUX function gets called to match a packet to a protocol it can refer to that list that it's stored the protocol detach is also handled by the plumber the plumber unplumbed function is called which then calls a function to detach the protocol from the interface the interface is the leak protocol function gets called which gives the interface an opportunity to clean up that d MUX descriptor to protocol family mapping once this is done the protocol detached callback is called to notify the protocol that it has been detached from the interface the outbound packet passes a little bit complex the protocol calls is net output and the iaf net output calls any interface filters pre output functions and give the filters a chance to process the packet the floor and interface header has been prepended once that's done the protocols pre output function is called the protocols pre output function is responsible for determining the destination link layer address this may require performing an art or whatever neighborhood neighbor discovery for ipv6 the protocols pre output function is also responsible for determining the frame type from there the protocol at the destination link layer address and the frame type are passed on to the interfaces framer function which then generates the interface header at that point the interface filters are all given an opportunity to filter the fully formed packet before the interfaces output function is called to transmit the packet on the inbound side the driver is responsible for calling is net input to pass the packet to the stack I have net input cuse the packet and at a later time the input thread comes along and dq's the packet it then calls the interfaces d MUX function to determine which protocol that packet belongs to the protocols interface filters have been called and finally the protocols input function is called to request a detach from the sack the driver can call is met detach the detaches are asynchronous with a call back when you call I've net detach there's a kernel event that gets generated to notify the stack and processes that the interface is going away and this can lead to the protocol this leads to the protocols being detached once all the protocols have been detached the interface is removed from the list of interfaces and the interfaces detached function is called back to let the interface know that it's safe to unload and that it won't be called again at this point to these stack releases its reference on the interface and if there are no other references the interfaces either recycled if read there are some locking considerations when we're working with or supplying an interface to the networking stack the access to your network interface is not serialized so you need to protect any of your data structures there are also some limitations in what you can do from your callbacks you cannot add another interface or add a protocol from any of the callbacks that you supply through the network interface in addition if you're going to try and detach an interface a protocol or an interface filter these operations will be delayed you do get some protection with the D mocks your D max function will never be called at the same time that either your ad protocol or delete protocol functions are being called in addition your ad protocol function will never be called at the same time as your delete protocol function is called so if you're using a linked list or something to keep track track of the Emacs descriptor to protocol family mappings you can manipulate that list in your add and delete protocol functions without worrying about locking it moving up the stack a little bit more we have the protocol plumbers which are responsible for gluing an interface to protocol and these have the knowledge of how a specific interface runs over a specific specific protocol runs over specific interface this is where knowledge of how to perform our or neighbor discovery or in the case of apple talk AARP would live the protocol plumber registers a plum and a nun plum function and the plum function is responsible for attaching the protocol and a nun plum function is responsible for detaching the protocol the protocol plumbers are documented in net / KPI underscore protocol that H in the kernel framework the pump the plum function typically calls is net attached protocol and it specifies a list of democracy descriptors which described in an interface specific way the type of packets that this protocol once the plumber also specifies an input function that will get called for any of the packets that are received for this protocol as well as a pre output function an event function for handling events on the interface and I octal for handling any protocol specific event I octaves on that interface and a detached function to get notified when the protocol has been detached the protocols input function is important this is where any art packets get handled or something similar depending on which protocol you're supporting in addition if you need to strip any headers off or do anything else so that you can just pass a rob packet to the protocol you do that in the plumber input function before you call proto input proto input is the function that you use to pass a packet to a protocol once you've taken anything out that's interface interface specific the protocol plumbers pre output function gets called on the outbound path just before the framer function for the interface and this gives the protocol plumber an opportunity to perform any arps the protocol plumber is responsible for determining the destination link layer address and a frame type so that those can be passed to the interface framer function when you're working with the protocol trump when you're working with a protocol plumber there are a number of locking considerations the unregister is synchronous and the unregister won't actually detach your protocols from interfaces so you need to keep a count of how many times you've attached if you're supplying any function pointers such as the input or pre output functions because until you've been detached from every interface your code still going to get called and if you unload before before you've been detached you're going to lead you're going to run into a panic there are some restrictions and what you can do and you're plumb and unplumbed functions you really you must not try and register or unregister another plumber and you also cannot trigger a plumber unplumbed function for any other protocols if you do this you'll run into a deadlock it's the top layer we have socket and the socket KPI gives you access to sockets inside of the colonel the KPI is based on the user space api's and it only lets you get access as a client of the socket you can't implement a protocol and interact with the socket in the ways that a protocol would in place of a struct socket pointer you now use a socket t and user space of course you use file descriptors but since this and in the kernel since the layout of a socket structure is private we're moving to be opaque type socket t sockets go through typical life cycle the socket is created various options are set the socket is connected data sent data is received in the socket is close the socket kpi is documented insist / kpi socket H in the kernel framework so to create a socket we use the function sock socket and it's very similar to the socket function in userspace it allows you to discuss the major differences that it allows you to specify an up call function and the up call function will let you get notification when data is ready so in this example we're creating a TCP socket and we're going to get back the socket we're passing in my up calls the up call function and my cookie is a parameter that will get passed to the up call function the sockets up call gets called when either data is waiting to be read or a connection is completed access to your up call function is not serialized so if you're going to be manipulating data in your up call be sure to take any lock the up call is also called on the fastpass if you make a blocking call in here you'll actually stop all incoming data if you make a blocking call in the socket in addition if you do any processing that's going to take a little while you should really do it elsewhere because you're going to hold up a lot of other stuff in this case we have an up call function the state's stored on the cookie and we check to see if we're connected and then we former read after taking the lock which should take a lock with a common set and then we deal with some of the data and then we would release the lock you can use sock sock ops and sakai octal to set various options there's also a sock get saw cops to retrieve options in this example we can see Sakai octos being used to set the socket to non-blocking i/o and the socks at sock opt is being used to set the receive buffer size to about 32 k there is no function that you'd usually do use to make a file descriptor non-blocking isn't available in the colonel because you're not working with a file descriptor here you just have a raw socket so in order to set non-blocking i/o you really need to call sock I octal connecting a socket is pretty straightforward sock connectors based on the connect to userspace call the difference between sock connect and the old esso connect he's done any programming and the colonel before with socket is that sock connect will actually block if the socket is a blocking socket if you set the sockets a non-blocking or you specify message don't wait is the last parameter then this will give you a non-blocking connect you can use the function sock is connected to determine whether or not the socket has completed its connection and you're up call will get called when this connection completes with either success or failure for sending there are two different functions both of them are based on sun message so they use a message header socks friends will send data that's stored in a kernel buffer and socks & M buff will send data that's stored in a chain of em buff in this example we're filling out a message header and we're setting the IO Beck to the kernel buffer that we have and we set up the name to point to the destination that we want and then we call sock send to send the data receiving is much is very similar there are two received functions and they're based on received message so there's Socrates and sock receive mbox sock receives receives data into a colonel offer and sock receive em buff receives data into the received data is the M buff in this example we're calling sock receives and we're filling out our message header first and we're specifying a buffering the kernel and when you're all done with the socket you use sock close you can't call sock clothes on a socket that's associated with a file descriptor because that'll really confuse the colonel since you since the socialist API doesn't do anything with the file descriptors you're going behind the file descriptors back there are some locking considerations don't make calls the sockets concurrently on different threads while you're protected in userspace through the file descriptor layer if you do this in the colonel we're not going through the file descriptor layer so that protection is pretty much gone and it especially if you're reading on one socket and close the socket on another socket you're going to run into a kernel panic pretty quickly in addition you're up call is reentrant so be sure to protect data and if you're going to do reads in two parts be sure that you take a lock so that somebody else can't if you do one little read to get a header that tells you how much data to read and you do another read after that there's always a chance that somebody might come in and do a read between those two so be careful about that so we have a socket filter KPI that lets you filter data and connections and other socket related operations at the socket layer these are commonly used for implementing a socket layer firewall so you don't have to deal with keeping track of all the state yourself you can actually let the stack do that you can also use it for implementing privacy controls or content filters as well as transparent proxies and the socket filter KPI is documented in this flash KPI underscore socket filthy about H in the kernel framework creating a socket filter is similar to creating an interface you fill out a structure that gives you the initial values in this case it's an S FLT underscore register structure and you call SFL te underscore filter to register the filter the filter gets associated with a domain a type and a protocol which are the same ten parameters that are used for creating a socket if you specify that you want a global filter that global filter will then be attached to any new sockets that are created after you've registered your filter and if you specify a programmatic filter those filters will be attached when somebody uses the s.o nke socket option to request your filter be attached to their socket again you get you can be attached in two different ways the global filters are attached when the sockets are created and the programmatic filters are attached with the fon k socket option when a socket is attached to when a sucker filters attached to a socket the attached function gets called and this gives the socket filter an opportunity to allocate some data for storing state that will be associated with that connection to that socket if you want to you can return an error to prevent your socket filter from being attached to the socket to unregister and detach your sockets you can call s FLT underscore unregister and this is also an asynchronous unregister with a call back to let you know when it's completed when you call this function it will prevent any more sockets from being attached to your socket filter and it will start detaching your socket filter from all the sockets that it's currently attached to so your socket filter will get detached when either the socket is closed or the filter is unregistered the SF unregistered callback that you can specify indicates that the detaches then complete and it's safe for you to unload for filtering inbound data in the past you had the filter or patch sb.append that's the append a door sb.append control it was kind of complicated and convoluted there's just one inbound data filter now called SF data and this function is not called in the context of the socket owners process so looking at the clock info to get information is not going to be useful from this function you can modify the data in the unbuffed chain the return value from this function is very important if he returns the data continues being processed as normal if you return II just returned the processing is going to stop and it's going to assume that you've taken responsibility for that data and that data will not be freed if you return any other error the processing will stop and the data will be freed if you do swallowed the data if by returning an error or eat just returned the process that owns the socket won't be woken up if you need to inject data later you can use the sock inject data in function for outbound data it's much the same there's an SF data out call back you can specify this is usually called in the context of the socket owners process the data can be modified and the return values are just the same for data out if you return to 0 then it processes as normal if your turn II just returned then your the processing stops and you're free to hold on to that data if you return any other value the processing stops and the data gets freed if you need to later inject some data that you would cute or something you can use sock inject data out you can also filter binds this lets you either bind to a different address from the requested one or prevent the bind all together if you need to bind to a different address call sock bind again on the same socket but with the new address that you want to bind to and then return Aegis return or if you got an error back from your second call to sock find you need to return that error if you do intercept the bind and bind to a different address you may want to also intercept the get sock main so that you can keep the process thinking that it connected to the fact that it found to the socket that it tried to bind to you can also filter connects both inbound and outbound for inbound connects you can only allow them or disallow them you can't change the address that the connection is coming in from for the outbound connections you can allow or disallow and you can also connect to a different address if you need to connect to a different address call stock connect again and specify the new address and then return e just return it's not connect succeeded if sock connect failed then go ahead and return the error that you got some socks and again you can intercept get pure name to keep the process thinking that it connected to the address that it had requested there's some additional filtered points for sockets the SF notify notifies you of socket state changes for example when you're being disconnected or you're in the disconnecting state you can also intercept socket options using the SF sets option and SF get option callbacks you can intercept I octal you can either handle them or block them you can also intercept listen to prevent processors from being able to create listening sockets so moving down the stack a little bit more we have IP filters IP filters give you a chance to filter packets at the IP layer and the really nice thing about IP filters is that they're the packets are passed to you after they've been reassembled on the inbound side so you don't have to deal with fragments on the outbound side you get the packets before they've been fragmented and the filter is also interface independent so you don't have to worry about attaching a different filter to every single interface that comes up and has IP attached to it you also get an opportunity to process the packets both before and after IPSec the IP filters go through a typical life cycle they're attached to either ipv4 or ipv6 and then they filter inbound and outbound data and then they're detached they're documented in that I net / KPI underscore IP filter H in the kernel framework the IP filters are attached using ipf add before an IPF add v6 and they both use the same structure to define a input and output filter function calling these functions returns a filter rep that you use for later detaching the filter the IPF input function is called for input for inbound packets and this is called after the pack has been reassembled and both before and after IPSec processing the output function is just the same but it's called excuse me called before we fragments a packet but also before and after we doing the IPSec processing so the function gets called and it's passed in the protocol and the protocol is specifies the protocol that we're currently processing at and you also get an offset from the beginning of the packet to that protocol so the beginning of the n buff chain will always start at the IP header or ipv6 header and then for an IPSec process you'll get called for an IPSec packet you might get called one with the ESP header with the offset from the IP packet to the ESP header and once IPSec is decrypted the packet you'll get called again with beyond with TCP or ICMP and the offset from the IP header to the ICMP header you can use IPS inject input and ipf inject outputs to inject data with ipf inject input it injects the data right after the packets have been reassembled in IP input if you pass a filter ref it will prevent this packet from getting processed again by both your filter and any filters before you if you've modified the packet you shouldn't pass a filter rest because that will prevent any of filters from having a chance to look at the new modified packet ipf inject output inject the data right into the IP output function and again you can pass a filter ref to avoid processing the packets twice to detach your filter you call ipf remove this detach is asynchronous and your ipf detach callback will get called to notify you when your filter has been detached and it's safe to unload there are some considerations with locking again access to your IP filter is not serialized so you need to be sure and protect any data structures that you've got in addition if you're going to call in a call to inject data you need to drop the locks before performing the inject because there's a chance that you might get called reentrant lee and if you try and take your lock again then you end up with a deadlock this is broken in the WWDC build you'll need to is the colonel that comes as part of the session 103 supplemental stuff moving down to the bottom of the stack we have the interface filters the interface filters let you filter inbound and outbound packet at the interface layer you can also filter the I octal interface filters are commonly used for a packet latest firewall or something like a virtual packet switch the interface filters are all also the replacements for the old protocol filter we no longer have protocol filters the interface filters are documented in net / KPI underscore interface filtered H in the kernel framework to attach an interface filter you fill out an iff filter structure and then you call I FLT attached this gives you an opportunity to specify a protocol it's important to note that the protocol doesn't specify you you aren't attached to that protocol attachment with the old protocol filters if you want to attach to IP / am0 you could only do that when i pea was attached to en 0 with the new interface filters you can specify that you want to get IP packets and you can attach the en 0 even when i pea isn't attached and your filter will remain attached until the interface goes away or until you detach it you just won't receive any packets unless I p is actually attached when you're ready to detach your filter you call I FLT underscore detach and this is asynchronous with a call back to let you know when it's safe to unload for filtering inbound packets the interfaces d MUX function gets called first to give it an opportunity to match the packet to a protocol so that we can know which interface filters to pass this to if you specify 0 for the protocol then you get all packets for any protocol or packets that don't match any protocol that's currently attached your iff input function will get called it's allowed to modify the packet if it does need to modify packet it should verify that the check sums are correct it's going to make any changes that affect the checksum and it should call em buff inbound modified and this will clear all the checksum flags so that we don't try and perform a hardware checks on later and run into problems the return values are important like in the socket filter if you return a 0 then the processing continues as normal if your turn II just returns the processing stops but the packets not freed to be responsible for either queuing it and rejecting it later or freeing it or doing whatever you want with it but you're responsible for freeing it he returned any other value it'll end up freeing the packet and the processing will stop on the outbound side you have two different places that you can filter there's a pre output function that lets you handle the packet before the interfaces framer has had a chance to pretend be interface header on the outbound you also have the ifs output function which gives you a chance to process the fully formed packet which includes the interface header if you're going to modify the packet you should call em buff outbound finalize which will force it to do any check sums and software that would have been done in hardware so you get a fully formed packet and it also clears all the checks on flag so if you reject it somewhere else you don't run into problems this may perform additional work such as inserting a deal and header although those packets probably won't get past your filter the return value is important and it's just like the return values for the socket filter and the inbound filter if you return 0 then processing continues as normal if your attorney just returned then you get to hold on to the packet if you return any error values in the packet gets free to the processing stop there are some additional places additional filters stuff you can set up at the interface layer the ISS event lets you receive notifications of events on the filter on the interface most common events are protocols attaching and detaching and the interface detach the iffi octal lets you filter the I Ospital functions so you can either intercept and handle your own I octal or you can intercept cocktails that would normally go to the interface if you need to inject inbound or outbound data you can use the if' net input function and i have met output functions if you need to communicate with a user space process the easiest way to do that is to use the colonel control KPI colonel control gives you a way to send small messages over a socket to user space it's commonly used for configuring a kernel extension or for retrieving information from a kernel extension the colonel control KPI is documented insist flash current control H in the kernel framework registering your kernel frame sorry registering your kernel control is done by filling out a current control register struck and calling control register this lets your kernel extension receive notification when a socket connects to your kernel control or when it disconnects it also lets you receive information from user land and you can get you can handle get and set socket options when you're done you can call control be register and that will unregister your control so when your control connect function gets called you can allocate any data that you need to associate with that connection to a specific socket and then you need to free that on your control disconnect call back if you need to send data to this to the process into the socket you can use ctrl + Q data and control and QM bus control and Q data works with a kernel kernel buffer and ctrl + qm buff works with data that's stored in an M buff chain with the colonel control access to it is not serialized but it is safe to send to the client at any time so the with the nothing see realized you really need to protect any data structures that you interact with whenever you get a call back to notify users data on the socket in addition is a another helper KPI the protocol layer and this is documented in net / KPI underscore protocol that H in the kernel framework this applies to you the hooks for injecting packets into a protocol there are two functions of the proto input function and the proto inject function the proto input function is intended for plumbers for passing packets up to IP or ipv6 or even Apple talk and they're really meant for the inbound packet path if you're going to be injecting packets from anywhere else in the stack where you're not on the inbound pass you need to use the proto inject function and these are the replacement for the net is are mechanisms that used to cue packets and then wake up the input thread in addition there's an M buff kpi that gives you access to the data that's stored in EM bus most of the packets all of the packets in the stack restored in n buff along with a bunch of other useful information the n buff kpi is based on the original n buff interfaces and we've added a lot of accessories the accessor functions names are based on the field name in the old n buff so for example n buff underscore lengths gets the length of the Amba the headers in the M buffs have changed a little bit and the result of those changes may be that you can't sort quite as much data in the namm buff that has a packet header or even a regular n buff and the cluster sizes might also change so don't make any assumptions about the amount of data that you can store in an n buff you can use em buff stat to get the values of all of the sizes for the various m buffs with headers and clusters we may be changing these things again we change them in Tiger to add support for and buff tags the M buff KPI is documented in this flash KPI underscore n buff eh there's still a number of things that are missing and we're working to get these in there as quickly as we can there's no access to the routing tables which makes it a little bit difficult for the plumbers to perform their our code correctly there's also no access to BPS but we will be providing access for tiger there are no accessories for indicating that you support hardware checksums or for detecting that a packet requires or request some hardware checksum there are the two functions for clearing those flags on both the inbound and outbound side there isn't a whole lot of sample code but we're working to change that in addition the colonel framework hasn't been completely cleaned up yet for Tiger GM we're hoping to get the colonel framework clean so that there aren't any data structures or functions in that framework that aren't part of the KPI in addition the list of exported symbols to the BFC colonel text hasn't been cleaned up yet so that there are still some symbols in there that we don't want to have as part of the KPI but for Tiger GM we will clean that up in addition we really need your feedback we have an email address set up kpi feedback at apple com and we need you to get started soon because the earlier that you give us feedback but easier it's going to be for us to get the changes that you need into the kernel so that you can get your network criminal extension working on tiger there are some resources for more information Craig Keithley is the IO technology invent evangelist and there's the KPI feedback email address kpi dash feedback and apple com in addition we have the some more reference stuff the NK the network colonel extension KPI reference is available online and also in the developer folder that gets installed with Tiger there's some more reference
