• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Macnetworkprog Digest, Vol 7, Issue 12
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Macnetworkprog Digest, Vol 7, Issue 12


  • Subject: Re: Macnetworkprog Digest, Vol 7, Issue 12
  • From: "Jay K. Robertson" <email@hidden>
  • Date: Fri, 26 Mar 2010 13:55:02 -0400

I believe that I have figured this out.

Although this does not appear to be documented anywhere, I have
discovered that the mbuf that the ipf_output hook function receives
can actually be a list of packets instead of a single packet.  As a
result, the hook function needs to iterate across all the packets in
the list by calling mbuf_nextpkt().  Otherwise, the hook function will
fail to process some packets.  This explains why the mbuf_freem_list()
function corrects the memory leak.

- Jay


On Fri, Mar 26, 2010 at 8:45 AM, Jay K. Robertson <email@hidden> wrote:
> Hi Brendan,
>
> I appreciate the suggestion, but I have tried that as well.  From my
> understanding of the documentation, the return codes mean the
> following:
> - 0 means accept the packet, and ip_output() will continue processing.
> - EJUSTRETURN means that the output hook function will take
> responsibility for the packet and must free it when it is done;
> ip_output() will stop processing.
> - Any other value means that ip_output() will free the packet and stop
> processing.
>
> Regardless of whether I return 1 and let ip_output() do the
> mbuf_freem(), or return EJUSTRETURN and do the mbuf_freem() myself, I
> still see a memory leak that is proportional to the number of TCP
> packets that are being processed.
>
> Strangely, I stumbled onto a workaround yesterday.  If I return
> EJUSTRETURN and use mbuf_freem_list() instead of mbuf_freem(), the
> memory leak does not occur.  It is my understanding that
> mbuf_freem_list() is not only supposed to free the current mbuf, it is
> also supposed to walk the list of mbufs that the current mbuf is a
> part of and free all of those as well.  It would seem that this
> behavior could break ip_output_list() completely, or at best, free
> packets that have yet to be processed by ip_output_list().  However, I
> haven't observed any adverse effects.
>
> I would really like to know what the proper solution is, and if this
> is the proper solution, why this is working.
>
> Thanks,
> - Jay
>
>
> On Thu, Mar 25, 2010 at 7:33 PM, Brendan Creane <email@hidden> wrote:
>> I have limited experience with IP filters, but for both socket filters and
>> interface filters, your filter routine needs to return EJUSTRETURN when it
>> consumes a packet, versus your current return value of 1. This seems to
>> contradict the documentation for IP filters, but you may try that as an
>> experiment.
>> regards, Brendan
>>>
>>> Message: 1
>>> Date: Wed, 24 Mar 2010 16:27:31 -0400
>>> From: "Jay K. Robertson" <email@hidden>
>>> Subject: Memory Leak Issue When Calling ipf_inject_output()
>>> To: email@hidden
>>> Message-ID:
>>>        <email@hidden>
>>> Content-Type: text/plain; charset=ISO-8859-1
>>>
>>> Hello,
>>>
>>> I am building an NKE on OS X 10.5.8 that captures packets using an IP
>>> filter on the outbound path.  My ipf_output function is below.  This
>>> is a simple function that receives IP packets, creates a new mbuf,
>>> copies the contents of the old mbuf into the new mbuf, and sends it
>>> out via ipf_inject_output().
>>>
>>> This function works fine except for one major problem.  While the
>>> packets appear to be sent correctly, if I send TCP packets outbound
>>> through this function, it appears to leak large amounts of memory.
>>> For some reason, this only happens on TCP packets--I don't see similar
>>> behavior when sending UDP packets.  Unfortunately, I don't have
>>> visibility into the kernel, so I can't really deduce why this is
>>> happening.
>>>
>>> To generate traffic, I am using iperf.  On the Mac running the NKE, I
>>> am using the following command line:
>>>  iperf -c (server IP) -t 60 -i 10
>>>
>>> And, on the remote system, I am using the following command line:
>>>  iperf -s
>>>
>>> When I run this, the system is unable to allocate new mbufs, mbuf
>>> tags, etc. after about 1 minute, and the system usually becomes
>>> unusable.  I am out of ideas on how to resolve this issue.  Can
>>> someone look at my code below and see what I could be doing wrong?
>>> I'm not sure if I am completing all of the steps correctly for
>>> capturing the packet, generating the checksums, injecting the packet,
>>> etc., as the documentation is practically non-existent.
>>>
>>> Thanks,
>>> - Jay
>>>
>>>
>>> static errno_t filter_out(void *cookie, mbuf_t *data, ipf_pktopts *opts)
>>> {
>>>    struct ip *iph = (struct ip *)mbuf_data(*data);
>>>    u_int8_t protocol = iph->ip_p;
>>>    int len = noths(iph->ip_len);
>>>    unsigned char buf[1500];
>>>    mbuf_t newdata = NULL;
>>>    errno_t err, ret = 0;       // Accept packets by default
>>>    int direction = 1;
>>>
>>>    // Filters packets using mbuf_tag_find()
>>>    if (0 == this->filter_match_tag(*data, direction)) {
>>>        MSG_INFO("Ignoring previously processed packet\n");
>>>        goto out;
>>>    }
>>>
>>>    // Selectively filter packets that we aren't interested in
>>>    if (!filter_ipv4_filter(*data, protocol)) {
>>>        goto out;
>>>    }
>>>
>>>    mbuf_outbound_finalize(*data, PF_INET, 0); // Finalize checksums
>>>    ret = 1; // Free original packet regardless of what happens
>>>
>>>    if (0 != (err = mbuf_copydata(*data, 0, len, buf))) {
>>>        MSG_ERR("Unable to copy mbuf to buf, err=%d\n", err);
>>>        goto out;
>>>    }
>>>
>>>    // At this point, it is intended that data will be sent to another
>>>    // thread for deferred processing.  That thread will construct and
>>>    // inject a new mbuf through ipf_inject_output().  For now, we
>>>    // simulate the construction of the new mbuf.
>>>
>>>    // Allocate the new packet
>>>    if (0 != mbuf_allocpacket(MBUF_DONTWAIT, 1500, NULL, &newdata)) {
>>>        MSG_ERR("Unable to allocate mbuf\n");
>>>        goto out;
>>>    // Copy data into new mbuf
>>>    } else if (0 != mbuf_copyback(newdata, 0, len, buf, MBUF_DONTWAIT)) {
>>>        MSG_ERR("Unable to copy buf to mbuf\n");
>>>        mbuf_freem(newdata);
>>>        goto out;
>>>    // Use mbuf_tag_allocate() to set tag so that we don't process this
>>> twice
>>>    } else if (0 != this->filter_set_tag(newdata, direction)) {
>>>        MSG_ERR("Unable to set tag\n");
>>>        mbuf_freem(newdata);
>>>        goto out;
>>>    } else {
>>>        mbuf_clear_csum_requested(newdata);
>>>        if (0 != (err = ipf_inject_output(newdata, NULL, NULL))) {
>>>            MSG_ERR("ipf_inject_output() failed, err=%d\n", err);
>>>        } else {
>>>            MSG_INFO("ipf_inject_output() succeeded\n");
>>>        }
>>>        // newdata is freed by ipf_inject_output() upon success or failure
>>>    }
>>>
>>> out:
>>>    return ret;
>>> }
>>>
>>>
>>> ------------------------------
>>>
>>> _______________________________________________
>>> Macnetworkprog mailing list
>>> email@hidden
>>> http://lists.apple.com/mailman/listinfo/macnetworkprog
>>>
>>> End of Macnetworkprog Digest, Vol 7, Issue 12
>>> *********************************************
>>
>>
>>  _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Macnetworkprog mailing list      (email@hidden)
>> Help/Unsubscribe/Update your Subscription:
>>
>>
>
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

References: 
 >Re: Macnetworkprog Digest, Vol 7, Issue 12 (From: Brendan Creane <email@hidden>)
 >Re: Macnetworkprog Digest, Vol 7, Issue 12 (From: "Jay K. Robertson" <email@hidden>)

  • Prev by Date: Re: Macnetworkprog Digest, Vol 7, Issue 12
  • Next by Date: smallest size of data in Gamekit ?
  • Previous by thread: Re: Macnetworkprog Digest, Vol 7, Issue 12
  • Next by thread: smallest size of data in Gamekit ?
  • Index(es):
    • Date
    • Thread