* Re: RFC: netfilter: synproxy iptables target
From: Patrick McHardy @ 2010-05-20 14:25 UTC (permalink / raw)
To: Changli Gao; +Cc: Netfilter Developer Mailing List, Linux Netdev List
In-Reply-To: <AANLkTimjY_0yKfMtAUxI7He-QH5R5AdDCR3V8eKSgbGq@mail.gmail.com>
Changli Gao wrote:
> On Thu, May 20, 2010 at 10:11 PM, Patrick McHardy <kaber@trash.net> wrote:
>> Changli Gao wrote:
>>> I have implemented a simple SYNPROXY iptables target. It is much like
>>> the SYNPROXY implementation in pf of OpenBSD, but won't have state
>>> until the first connection is established with the help of syncookies.
>>> The code is hosted at github:
>>>
>>> http://github.com/xiaosuo/xiaosuo/tree/master/synproxy/
>>>
>>> Currently, it can work with firewall and local socket.
>>>
>>> It is in the very early stage, and ugly. And I will add --timeout
>>> parameter to this target as TCP_DFER_ACCEPT, so I can do NAT basing on
>>> the request data.
>>>
>>> i.e.
>>>
>>> iptables -t nat -A OUTPUT -p tcp -m synproxy --http-url "*.jpg" -j
>>> DNAT --to-destination $image_http_server:80
>>>
>>> And is there any chance to merge it into mainline?
>> If you can state a good use case, sure. I don't know much about the
>> PF synproxy myself.
>>
>
> pure synproxy can be used on firewall to protect the internal servers,
> which don't support neither syncookies and synproxy, from the attack
> of SYN-flood.
>
> synproxy with defered connection relay acts as a layer 7 proxy, but
> works in kernel space totally, unlike tcp splice tech., which needs
> the applications in user space parse the requests, and establish the
> connections.
I can't say much before seeing any code, but no general objections
from my side.
^ permalink raw reply
* Re: [net-next-2.6 V9 PATCH 1/2] Add netlink support for virtual port management (was iovnl)
From: Patrick McHardy @ 2010-05-20 14:24 UTC (permalink / raw)
To: Scott Feldman; +Cc: davem, netdev, chrisw, arnd
In-Reply-To: <20100518054833.21787.45456.stgit@savbu-pc100.cisco.com>
Scott Feldman wrote:
> From: Scott Feldman <scofeldm@cisco.com>
>
> Add new netdev ops ndo_{set|get}_vf_port to allow setting of
> port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/
> RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
> (added to end of IFLA_cmd list). These are both nested atrtibutes
> using this layout:
>
>...
Appologies for the delay, my mailserver failed me once again :|
This version looks very good to me, just one question:
> +static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct nlattr *vf_ports;
> + struct nlattr *vf_port;
> + int vf;
> + int err;
> +
> + vf_ports = nla_nest_start(skb, IFLA_VF_PORTS);
> + if (!vf_ports)
> + return -EMSGSIZE;
> +
> + for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
> + vf_port = nla_nest_start(skb, IFLA_VF_PORT);
> + if (!vf_port) {
> + nla_nest_cancel(skb, vf_ports);
> + return -EMSGSIZE;
> + }
> + NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
> + err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
> + if (err) {
> +nla_put_failure:
> + nla_nest_cancel(skb, vf_port);
> + continue;
Are you sure you want to continue here? During a full dump
this means that the last VF port fitting in the skb will most
likely be incomplete since the higher layer code won't
notice that the size was exceeded and the entry should be
dumped into another skb.
> + }
> + nla_nest_end(skb, vf_port);
> + }
> +
> + nla_nest_end(skb, vf_ports);
> +
> + return 0;
> +}
^ permalink raw reply
* Re: RFC: netfilter: synproxy iptables target
From: Changli Gao @ 2010-05-20 14:21 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List, Linux Netdev List
In-Reply-To: <4BF54310.6030004@trash.net>
On Thu, May 20, 2010 at 10:11 PM, Patrick McHardy <kaber@trash.net> wrote:
> Changli Gao wrote:
>> I have implemented a simple SYNPROXY iptables target. It is much like
>> the SYNPROXY implementation in pf of OpenBSD, but won't have state
>> until the first connection is established with the help of syncookies.
>> The code is hosted at github:
>>
>> http://github.com/xiaosuo/xiaosuo/tree/master/synproxy/
>>
>> Currently, it can work with firewall and local socket.
>>
>> It is in the very early stage, and ugly. And I will add --timeout
>> parameter to this target as TCP_DFER_ACCEPT, so I can do NAT basing on
>> the request data.
>>
>> i.e.
>>
>> iptables -t nat -A OUTPUT -p tcp -m synproxy --http-url "*.jpg" -j
>> DNAT --to-destination $image_http_server:80
>>
>> And is there any chance to merge it into mainline?
>
> If you can state a good use case, sure. I don't know much about the
> PF synproxy myself.
>
pure synproxy can be used on firewall to protect the internal servers,
which don't support neither syncookies and synproxy, from the attack
of SYN-flood.
synproxy with defered connection relay acts as a layer 7 proxy, but
works in kernel space totally, unlike tcp splice tech., which needs
the applications in user space parse the requests, and establish the
connections.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: RFC: netfilter: synproxy iptables target
From: Patrick McHardy @ 2010-05-20 14:11 UTC (permalink / raw)
To: Changli Gao; +Cc: Netfilter Developer Mailing List, Linux Netdev List
In-Reply-To: <AANLkTimp6S7MpwDAT8l-M0ZWjs2HIcUEfL5f8j9-QDZh@mail.gmail.com>
Changli Gao wrote:
> I have implemented a simple SYNPROXY iptables target. It is much like
> the SYNPROXY implementation in pf of OpenBSD, but won't have state
> until the first connection is established with the help of syncookies.
> The code is hosted at github:
>
> http://github.com/xiaosuo/xiaosuo/tree/master/synproxy/
>
> Currently, it can work with firewall and local socket.
>
> It is in the very early stage, and ugly. And I will add --timeout
> parameter to this target as TCP_DFER_ACCEPT, so I can do NAT basing on
> the request data.
>
> i.e.
>
> iptables -t nat -A OUTPUT -p tcp -m synproxy --http-url "*.jpg" -j
> DNAT --to-destination $image_http_server:80
>
> And is there any chance to merge it into mainline?
If you can state a good use case, sure. I don't know much about the
PF synproxy myself.
^ permalink raw reply
* Re: [PATCH iproute] ip: add support for multicast rules
From: Patrick McHardy @ 2010-05-20 14:01 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Linux Netdev List
In-Reply-To: <20100519090354.6dc6d82b@nehalam>
Stephen Hemminger wrote:
> On Tue, 13 Apr 2010 17:06:24 +0200
> Patrick McHardy <kaber@trash.net> wrote:
>
>> This patch adds support for a "ip mrule" command, which is used
>> to configure multicast routing rules.
>>
>> The corresponding kernel patches have been sent to Dave and
>> should (hopefully) appear in net-next soon.
>
> The fib_rules.h file in iproute2 is kept in sync with the kernel
> headers. But I do not see the definitions of FIB_RULES_IPV4 etc
> in net-next kernel. What happened to this?
Those got changed again during the addition of IPv6 support.
I'll send a new version shortly, including IPv6 support.
^ permalink raw reply
* [PATCH] sh_eth: Fix memleak in sh_mdio_release
From: Denis Kirjanov @ 2010-05-20 14:00 UTC (permalink / raw)
To: davem; +Cc: shimoda.yoshihiro, iwamatsu, morimoto.kuninori, netdev
Allocated memory for IRQs should be freed when releasing the mii_bus
Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
---
drivers/net/sh_eth.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 586ed09..501a55f 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -1294,6 +1294,9 @@ static int sh_mdio_release(struct net_device *ndev)
/* remove mdio bus info from net_device */
dev_set_drvdata(&ndev->dev, NULL);
+ /* free interrupts memory */
+ kfree(bus->irq);
+
/* free bitbang info */
free_mdio_bitbang(bus);
^ permalink raw reply related
* Re: [PATCH] netfilter: fix description of expected checkentry return code on xt_target
From: Patrick McHardy @ 2010-05-20 13:59 UTC (permalink / raw)
To: Luciano Coelho; +Cc: netfilter-devel, netdev
In-Reply-To: <1274126430-13744-1-git-send-email-luciano.coelho@nokia.com>
Luciano Coelho wrote:
> The text describing the return codes that are expected on calls to
> checkentry() was incorrect. Instead of returning true or false, or an error
> code, it should return 0 or an error code.
Applied, thanks.
^ permalink raw reply
* Re: will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
From: Eilon Greenstein @ 2010-05-20 12:20 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Jon Zhou, netdev@vger.kernel.org
In-Reply-To: <1274356826.4046.29.camel@edumazet-laptop>
On Thu, 2010-05-20 at 05:00 -0700, Eric Dumazet wrote:
> Le jeudi 20 mai 2010 à 14:46 +0300, Eilon Greenstein a écrit :
> > On Wed, 2010-05-19 at 22:37 -0700, Jon Zhou wrote:
> > > will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
> > >
> > > let 's take broadcom 57711 bnx2x_main.c as an example:
> > >
> > > #1 packet1->queue=1
> > > #2 packet2->queue=1
> > >
> > > will cpu1 and cpu2 execute the function " bnx2x_rx_int" in parallel, to receive packet1 & packet2
> > Both packets will be handled by the same queue and the queue processing
> > is serialized - so the packets will be handled one after the other.
>
> I am scratching my head to understand both the question and your
> answer...
>
I was trying to say that since both packets are handled on the same
queue - it is handled one after the other and not by two different CPUs
working on the same queue at once.
> if cpu1 is handling an interrupt, cpu2 cannot handle an interrupt at the
> same time for same queue. It must be for a different queue.
>
> Therefore, packets will be handled in parallel.
What do you mean "in parallel"? As you wrote above, only one cpu is
handling the packets from that queue, and since the hash is the same,
even RPS will not allow different CPUs to handle those 2 packets.
>
> Serialization might be done later, at socket layer to queue packets in a
> receive queue for example, if both packets must be delivered on same
> socket.
Though this is always true, the case of receiving packets on the same
queue is even simpler, is not it?
^ permalink raw reply
* Re: will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
From: Eric Dumazet @ 2010-05-20 12:00 UTC (permalink / raw)
To: eilong; +Cc: Jon Zhou, netdev@vger.kernel.org
In-Reply-To: <1274355967.17395.5.camel@lb-tlvb-eilong.il.broadcom.com>
Le jeudi 20 mai 2010 à 14:46 +0300, Eilon Greenstein a écrit :
> On Wed, 2010-05-19 at 22:37 -0700, Jon Zhou wrote:
> > will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
> >
> > let 's take broadcom 57711 bnx2x_main.c as an example:
> >
> > #1 packet1->queue=1
> > #2 packet2->queue=1
> >
> > will cpu1 and cpu2 execute the function " bnx2x_rx_int" in parallel, to receive packet1 & packet2
> Both packets will be handled by the same queue and the queue processing
> is serialized - so the packets will be handled one after the other.
I am scratching my head to understand both the question and your
answer...
if cpu1 is handling an interrupt, cpu2 cannot handle an interrupt at the
same time for same queue. It must be for a different queue.
Therefore, packets will be handled in parallel.
Serialization might be done later, at socket layer to queue packets in a
receive queue for example, if both packets must be delivered on same
socket.
^ permalink raw reply
* Re: will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
From: Eilon Greenstein @ 2010-05-20 11:46 UTC (permalink / raw)
To: Jon Zhou; +Cc: netdev@vger.kernel.org
In-Reply-To: <4A6A2125329CFD4D8CC40C9E8ABCAB9F2497F5B7D6@MILEXCH2.ds.jdsu.net>
On Wed, 2010-05-19 at 22:37 -0700, Jon Zhou wrote:
> will 2 cpu simultaneously process packets which have same hash value on multiqueue nic?
>
> let 's take broadcom 57711 bnx2x_main.c as an example:
>
> #1 packet1->queue=1
> #2 packet2->queue=1
>
> will cpu1 and cpu2 execute the function " bnx2x_rx_int" in parallel, to receive packet1 & packet2
Both packets will be handled by the same queue and the queue processing
is serialized - so the packets will be handled one after the other.
Regards,
Eilon
^ permalink raw reply
* Re: [PATCH 06/11] netdev: bfin_mac: avoid tx skb overflows in the tx DMA ring
From: Sonic Zhang @ 2010-05-20 10:36 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20100520.030835.267363374.davem@davemloft.net>
On Thu, May 20, 2010 at 6:08 PM, David Miller <davem@davemloft.net> wrote:
> From: Sonic Zhang <sonic.adi@gmail.com>
> Date: Thu, 20 May 2010 17:38:07 +0800
>
>> On Thu, May 20, 2010 at 4:12 AM, David Miller <davem@davemloft.net> wrote:
>>> From: Sonic Zhang <sonic.adi@gmail.com>
>>> Date: Wed, 19 May 2010 17:23:16 +0800
>>>
>>>> No, this doesn't happen, because before ndo_start_xmit() returns, the
>>>> old TX buffers and skbs in the ring, which finished DMA operation, are
>>>> freed. The only difference is that the free operation of a skb is done
>>>> in next tx transfer.
>>>
>>> This is still illegal.
>>>
>>> What if TX activity stops right then, and there is no "next tx
>>> transfer"?
>>>
>> The skb remain in the TX ring will be freed finally when ndo_stop() is
>> called to shutdown the network. So, this is not a problem.
>
> You really don't understand me, and I'm starting to get really
> frustrated. You must free all packets in your TX ring in a very
> small, finite, amount of time. This is not optional. And this
> must happen regardless of what TX traffic which occurs in the future,
> that means it must happen even if TX traffic suddenly stops.
>
OK. I didn't figure out that the socket may not be closed if its skbs
stay active somewhere in system for a long time. Thanks for your
explanation. I will send a new patch to enabled tx interrupt and free
skb from tx ring immediately.
Sonic
> Your driver's behavior is absolutely not acceptable.
>
> Leaving the SKB In the TX ring like that means that potentially there
> is a socket in the system or other major resource that cannot be released
> and freed up.
>
> Please stop your driver from keeping packets in the TX ring indefinitely.
>
^ permalink raw reply
* Re: [PATCH 06/11] netdev: bfin_mac: avoid tx skb overflows in the tx DMA ring
From: Sonic Zhang @ 2010-05-20 10:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20100520.030835.267363374.davem@davemloft.net>
On Thu, May 20, 2010 at 6:08 PM, David Miller <davem@davemloft.net> wrote:
> From: Sonic Zhang <sonic.adi@gmail.com>
> Date: Thu, 20 May 2010 17:38:07 +0800
>
>> On Thu, May 20, 2010 at 4:12 AM, David Miller <davem@davemloft.net> wrote:
>>> From: Sonic Zhang <sonic.adi@gmail.com>
>>> Date: Wed, 19 May 2010 17:23:16 +0800
>>>
>>>> No, this doesn't happen, because before ndo_start_xmit() returns, the
>>>> old TX buffers and skbs in the ring, which finished DMA operation, are
>>>> freed. The only difference is that the free operation of a skb is done
>>>> in next tx transfer.
>>>
>>> This is still illegal.
>>>
>>> What if TX activity stops right then, and there is no "next tx
>>> transfer"?
>>>
>> The skb remain in the TX ring will be freed finally when ndo_stop() is
>> called to shutdown the network. So, this is not a problem.
>
> You really don't understand me, and I'm starting to get really
> frustrated. You must free all packets in your TX ring in a very
> small, finite, amount of time. This is not optional. And this
> must happen regardless of what TX traffic which occurs in the future,
> that means it must happen even if TX traffic suddenly stops.
>
> Your driver's behavior is absolutely not acceptable.
>
> Leaving the SKB In the TX ring like that means that potentially there
> is a socket in the system or other major resource that cannot be released
> and freed up.
>
> Please stop your driver from keeping packets in the TX ring indefinitely.
>
Forgot to CC netdev mailing list in my last reply.
Try again.
Sonic
^ permalink raw reply
* Re: loosing IPMI-card by loading netconsole
From: Henning Fehrmann @ 2010-05-20 10:16 UTC (permalink / raw)
To: Tejun Heo
Cc: Ronciak, John, Kirsher, Jeffrey T, Brandeburg, Jesse,
Allan, Bruce W, Waskiewicz Jr, Peter P, netdev@vger.kernel.org,
Carsten Aulbert
In-Reply-To: <20100518131216.GA24750@localhost>
Hello,
>
>
> Let me re-describe the symptoms.
> I am not loading any ipmi related modules and not the netconsole
> module.
> When booting out current 2.6.32 kernel we can not access the IPMI
> remotely.
>
> We had one case where the IPMI card was accessible while using this
> kernel but probably due to the fact that eth0 was removed. We do not
> consider this case anymore.
>
> This problem does not occur when using an older kernel.
>
> It has likely nothing to do with netconsole.
>
> Here is the bisecting result:
>
> The sha1 sum of the first bad commit is:
> 6e50912a442947d5fafd296ca6fdcbeb36b163ff
>
> Hence, the last good commit has:
> b2f8f7525c8aa1fdd8ad8c72c832dfb571d5f768
I 'reverse patched' the changes:
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index e909f96..1342e0b 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -427,6 +427,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&crc_stripping, &opt, adapter);
if (crc_stripping == OPTION_ENABLED)
adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ } else {
+ adapter->flags2 |= FLAG2_CRC_STRIPPING;
}
}
{ /* Kumeran Lock Loss Workaround */
and compiled the kernel. This kernel works and the IPMI card is remotely accessible.
Can we savely remove this two lines or are we running into other problems?
Cheers,
Henning
^ permalink raw reply related
* RFC: netfilter: synproxy iptables target
From: Changli Gao @ 2010-05-20 9:46 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List, Linux Netdev List
I have implemented a simple SYNPROXY iptables target. It is much like
the SYNPROXY implementation in pf of OpenBSD, but won't have state
until the first connection is established with the help of syncookies.
The code is hosted at github:
http://github.com/xiaosuo/xiaosuo/tree/master/synproxy/
Currently, it can work with firewall and local socket.
It is in the very early stage, and ugly. And I will add --timeout
parameter to this target as TCP_DFER_ACCEPT, so I can do NAT basing on
the request data.
i.e.
iptables -t nat -A OUTPUT -p tcp -m synproxy --http-url "*.jpg" -j
DNAT --to-destination $image_http_server:80
And is there any chance to merge it into mainline?
--
Regards,
Changli Gao(xiaosuo@gmail.com)
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: tun: Use netif_receive_skb instead of netif_rx
From: Thomas Graf @ 2010-05-20 9:40 UTC (permalink / raw)
To: Herbert Xu; +Cc: Eric Dumazet, David Miller, bmb, nhorman, nhorman, netdev
In-Reply-To: <1274343043.23393.7.camel@lsx.localdomain>
On Thu, 2010-05-20 at 10:10 +0200, Thomas Graf wrote:
> There is a fundamental problem with this. The process needs to be
> associated with the cgroup before any sockets get created. Sockets
> are often created right after the application starts. This means that
> the only viable option is to start each application in a wrapper which
> assigns itself to the cgroup and then forks the application as its
> child. If a task is associated with a cgroup after it has started it
> may lead to unpredictable outcome because only some of the sockets
> may end up being classified.
>
> This was the actual reason for the old method.
Disregard this. I didn't read your latest patch correctly.
^ permalink raw reply
* [PATCH] net: remove zap_completion_queue
From: Eric Dumazet @ 2010-05-20 9:16 UTC (permalink / raw)
To: David Miller; +Cc: netdev
netpoll does an interesting work in zap_completion_queue(), but this was
before we did skb orphaning before delivering packets to device.
It now makes sense to add a test in dev_kfree_skb_irq() to not queue a
skb if already orphaned, and to remove netpoll zap_completion_queue() as
a bonus.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/core/dev.c | 4 +++-
net/core/netpoll.c | 31 -------------------------------
2 files changed, 3 insertions(+), 32 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6c82065..37f1641 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1578,7 +1578,9 @@ EXPORT_SYMBOL(__netif_schedule);
void dev_kfree_skb_irq(struct sk_buff *skb)
{
- if (atomic_dec_and_test(&skb->users)) {
+ if (!skb->destructor)
+ dev_kfree_skb(skb);
+ else if (atomic_dec_and_test(&skb->users)) {
struct softnet_data *sd;
unsigned long flags;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 94825b1..e034342 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -49,7 +49,6 @@ static atomic_t trapped;
(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
sizeof(struct iphdr) + sizeof(struct ethhdr))
-static void zap_completion_queue(void);
static void arp_reply(struct sk_buff *skb);
static unsigned int carrier_timeout = 4;
@@ -197,7 +196,6 @@ void netpoll_poll_dev(struct net_device *dev)
service_arp_queue(dev->npinfo);
- zap_completion_queue();
}
void netpoll_poll(struct netpoll *np)
@@ -221,40 +219,11 @@ static void refill_skbs(void)
spin_unlock_irqrestore(&skb_pool.lock, flags);
}
-static void zap_completion_queue(void)
-{
- unsigned long flags;
- struct softnet_data *sd = &get_cpu_var(softnet_data);
-
- if (sd->completion_queue) {
- struct sk_buff *clist;
-
- local_irq_save(flags);
- clist = sd->completion_queue;
- sd->completion_queue = NULL;
- local_irq_restore(flags);
-
- while (clist != NULL) {
- struct sk_buff *skb = clist;
- clist = clist->next;
- if (skb->destructor) {
- atomic_inc(&skb->users);
- dev_kfree_skb_any(skb); /* put this one back */
- } else {
- __kfree_skb(skb);
- }
- }
- }
-
- put_cpu_var(softnet_data);
-}
-
static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
{
int count = 0;
struct sk_buff *skb;
- zap_completion_queue();
refill_skbs();
repeat:
^ permalink raw reply related
* Issue on RTL8169scd(l), can not transmit packet
From: steven @ 2010-05-20 8:21 UTC (permalink / raw)
To: netdev; +Cc: romieu
Dear All,
I am porting openPOWERLINK to Loongson/MIPS platform, so I have to write
a driver for RTL8169scl(RTL8169scd in kernel) firstly.
Now, my driver could receive packet(confirmed by printing the content of
packets and comparing them with the data wireshark captured).
But RTL8169 didn't send any packet(I use wireshark to capture the
packet). And I found some bits in Tx Desc(Transmit Descriptor) has been
modified, such as OWN, that's to say RTL8169 could read/write the
transmit descriptor buffer. Things seems OK, but I can not capture any
packet.()
I use pci_alloc_consistent to allocate the memory for TxDesc/RxDesc Tx
buffer/Rx buffer. The first field of my TxDesc is 0xb000003c.
The environment:
Target<===> HUB <===>PC_with_wireshark
The LED(whose port connects to the target) on HUB doesn't flash when the
target keeps sending packet or it receives packets.
I print the content of all the registers of RTL8169 in Linux kernel, I
found the configuration in kernel and in my driver are the
same except PHY Access, but the config of all the PHY regs are the same
with kernel's. There is no "system error interrupt" occurs, but I am not
sure whether it will screw up.
[14403.742503] 0x10---------0x9EAD4000
[14403.742991] 0x14---------0x00000000
[14403.743478] 0x18---------0x00000000
[14403.744799] 0x1C---------0x00000000
[14403.745309] 0x20---------0x9EB18000
[14403.745801] 0x24---------0x00000000
[14403.746289] 0x28---------0x05744700
[14403.746778] 0x2C---------0xB61C07FB
[14403.747265] 0x37---------0x0C
[14403.747702] 0x38---------0x00
[14403.749221] 0x3C---------0xC1FF
[14403.749692] 0x3E---------0x0000
[14403.750146] 0x40---------0x1B000600
[14403.750636] 0x44---------0x00000000
[14403.751123] 0x48---------0x09AF2BDA
[14403.751612] 0x50---------0x00
[14403.752973] 0x51---------0x05
[14403.753423] 0x52---------0xCD
[14403.753860] 0x53---------0x00
[14403.754295] 0x54---------0xA1
[14403.754731] 0x55---------0x00
[14403.755164] 0x56---------0x01
[14403.755600] 0x58---------0x00000000
[14403.757212] 0x60---------0x00000000
[14403.757722] 0x6c---------0x06
[14403.758160] 0xC4---------0x8EAD
[14403.758771] 0xC6---------0x7962
[14403.759230] 0xC8---------0x1020
[14403.759682] 0xCA---------0x45D6
[14403.761115] 0xCC---------0x6353
[14403.761589] 0xDA---------0x4000
[14403.762047] 0xE0---------0x0028
[14403.762500] 0xE4---------0x9E76C000
[14403.762987] 0xE8---------0x00000000
[14403.763475] 0xEC---------0x0000003F
Does anyone have some idea? Thank you very very much.
Steven
^ permalink raw reply
* Re: tun: Use netif_receive_skb instead of netif_rx
From: Thomas Graf @ 2010-05-20 8:10 UTC (permalink / raw)
To: Herbert Xu; +Cc: Eric Dumazet, David Miller, bmb, nhorman, nhorman, netdev
In-Reply-To: <20100520065242.GA8719@gondor.apana.org.au>
On Thu, 2010-05-20 at 16:52 +1000, Herbert Xu wrote:
> The value is set at socket creation time. So all sockets created
> via socket(2) automatically gains the ID of the thread creating it.
> Whenever another process touches the socket by either reading or
> writing to it, we will change the socket classid to that of the
> process if it has a valid (non-zero) classid.
There is a fundamental problem with this. The process needs to be
associated with the cgroup before any sockets get created. Sockets
are often created right after the application starts. This means that
the only viable option is to start each application in a wrapper which
assigns itself to the cgroup and then forks the application as its
child. If a task is associated with a cgroup after it has started it
may lead to unpredictable outcome because only some of the sockets
may end up being classified.
This was the actual reason for the old method.
^ permalink raw reply
* [PATCH] net: Use __this_cpu_inc() in fast path
From: Eric Dumazet @ 2010-05-20 8:07 UTC (permalink / raw)
To: David Miller; +Cc: netdev
This patch saves 224 bytes of text on my machine.
__this_cpu_inc() generates a single instruction, using no scratch
registers :
65 ff 04 25 a8 30 01 00 incl %gs:0x130a8
instead of :
48 c7 c2 80 30 01 00 mov $0x13080,%rdx
65 48 8b 04 25 88 ea 00 00 mov %gs:0xea88,%rax
83 44 10 28 01 addl $0x1,0x28(%rax,%rdx,1)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/core/dev.c | 3 +--
net/ipv4/route.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6c82065..76475f2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2826,8 +2826,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
skb->dev = master;
}
- __get_cpu_var(softnet_data).processed++;
-
+ __this_cpu_inc(softnet_data.processed);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
skb->mac_len = skb->network_header - skb->mac_header;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 560acc6..8495bce 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -253,8 +253,7 @@ static unsigned rt_hash_mask __read_mostly;
static unsigned int rt_hash_log __read_mostly;
static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
-#define RT_CACHE_STAT_INC(field) \
- (__raw_get_cpu_var(rt_cache_stat).field++)
+#define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx,
int genid)
^ permalink raw reply related
* Re: [PATCH net-next-2.6 0/8] CAIF: Bugfixes and updates
From: David Miller @ 2010-05-20 7:56 UTC (permalink / raw)
To: sjur.brandeland
Cc: netdev, marcel, daniel.martensson, linus.walleji, sjurbren
In-Reply-To: <1274341448-14924-1-git-send-email-sjur.brandeland@stericsson.com>
From: sjur.brandeland@stericsson.com
Date: Thu, 20 May 2010 09:44:00 +0200
> I have a series of CAIF bug fixes and changes. I realize you sent
> the pull request to linux-next yesterday, am I too late for the
> merge window with functional changes?
Yes.
Send me bug fixes only.
^ permalink raw reply
* [PATCH net-next-2.6 8/8] caif: Fixed splint warnings
From: sjur.brandeland @ 2010-05-20 7:44 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, linus.walleji, sjurbren,
Sjur Braendeland
In-Reply-To: <1274341448-14924-8-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Compiled with splint and tested on 64bit x86.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
net/caif/caif_socket.c | 10 +++++-----
net/caif/cfcnfg.c | 2 +-
net/caif/cfmuxl.c | 3 ++-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 4bf2ed6..0fa614f 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -60,7 +60,7 @@ struct debug_fs_counter {
atomic_t num_rx_flow_off;
atomic_t num_rx_flow_on;
};
-struct debug_fs_counter cnt;
+static struct debug_fs_counter cnt;
#define dbfs_atomic_inc(v) atomic_inc(v)
#define dbfs_atomic_dec(v) atomic_dec(v)
#else
@@ -129,13 +129,13 @@ static void caif_read_unlock(struct sock *sk)
mutex_unlock(&cf_sk->readlock);
}
-int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
+static int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
{
/* A quarter of full buffer is used a low water mark */
return cf_sk->sk.sk_rcvbuf / 4;
}
-void caif_flow_ctrl(struct sock *sk, int mode)
+static void caif_flow_ctrl(struct sock *sk, int mode)
{
struct caifsock *cf_sk;
cf_sk = container_of(sk, struct caifsock, sk);
@@ -147,7 +147,7 @@ void caif_flow_ctrl(struct sock *sk, int mode)
* Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are
* not dropped, but CAIF is sending flow off instead.
*/
-int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int err;
int skb_len;
@@ -1184,7 +1184,7 @@ static struct net_proto_family caif_family_ops = {
.owner = THIS_MODULE,
};
-int af_caif_init(void)
+static int af_caif_init(void)
{
int err = sock_register(&caif_family_ops);
if (!err)
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index ca4077c..4d5fe51 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -258,7 +258,7 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
{
}
-int protohead[CFCTRL_SRV_MASK] = {
+static int protohead[CFCTRL_SRV_MASK] = {
[CFCTRL_SRV_VEI] = 4,
[CFCTRL_SRV_DATAGRAM] = 7,
[CFCTRL_SRV_UTIL] = 4,
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
index 7372f27..b029872 100644
--- a/net/caif/cfmuxl.c
+++ b/net/caif/cfmuxl.c
@@ -174,10 +174,11 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id)
spin_lock(&muxl->receive_lock);
up = get_up(muxl, id);
if (up == NULL)
- return NULL;
+ goto out;
memset(muxl->up_cache, 0, sizeof(muxl->up_cache));
list_del(&up->node);
cfsrvl_put(up);
+ out:
spin_unlock(&muxl->receive_lock);
return up;
}
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 7/8] caif: Bugfix - Poll can't return POLLHUP while connecting.
From: sjur.brandeland @ 2010-05-20 7:44 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, linus.walleji, sjurbren,
Sjur Braendeland
In-Reply-To: <1274341448-14924-7-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
While connecting poll should not return POLLHUP,
but POLLOUT when connected.
Also fixed the sysfs for flow control that was not counting correctly.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
net/caif/caif_socket.c | 22 ++++++----------------
1 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 2c2f7d7..4bf2ed6 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -139,7 +139,7 @@ void caif_flow_ctrl(struct sock *sk, int mode)
{
struct caifsock *cf_sk;
cf_sk = container_of(sk, struct caifsock, sk);
- if (cf_sk->layer.dn)
+ if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd)
cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode);
}
@@ -163,9 +163,8 @@ int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
atomic_read(&cf_sk->sk.sk_rmem_alloc),
sk_rcvbuf_lowwater(cf_sk));
set_rx_flow_off(cf_sk);
- if (cf_sk->layer.dn)
- cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
- CAIF_MODEMCMD_FLOW_OFF_REQ);
+ dbfs_atomic_inc(&cnt.num_rx_flow_off);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
}
err = sk_filter(sk, skb);
@@ -176,9 +175,8 @@ int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
trace_printk("CAIF: %s():"
" sending flow OFF due to rmem_schedule\n",
__func__);
- if (cf_sk->layer.dn)
- cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
- CAIF_MODEMCMD_FLOW_OFF_REQ);
+ dbfs_atomic_inc(&cnt.num_rx_flow_off);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
}
skb->dev = NULL;
skb_set_owner_r(skb, sk);
@@ -286,17 +284,13 @@ static void caif_check_flow_release(struct sock *sk)
{
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
- if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL)
- return;
-
if (rx_flow_is_on(cf_sk))
return;
if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) {
dbfs_atomic_inc(&cnt.num_rx_flow_on);
set_rx_flow_on(cf_sk);
- cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
- CAIF_MODEMCMD_FLOW_ON_REQ);
+ caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ);
}
}
@@ -1019,10 +1013,6 @@ static unsigned int caif_poll(struct file *file,
(sk->sk_shutdown & RCV_SHUTDOWN))
mask |= POLLIN | POLLRDNORM;
- /* Connection-based need to check for termination and startup */
- if (sk->sk_state == CAIF_DISCONNECTED)
- mask |= POLLHUP;
-
/*
* we set writable also when the other side has shut down the
* connection. This prevents stuck sockets.
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 6/8] caif: Use link layer MTU instead of fixed MTU
From: sjur.brandeland @ 2010-05-20 7:44 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, linus.walleji, sjurbren,
Sjur Braendeland
In-Reply-To: <1274341448-14924-6-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Removed MTU, head and tail-room constants CAIF_MAX_FRAMESIZE,
CAIF_MAX_PAYLOAD_SIZE, CAIF_NEEDED_HEADROOM, CAIF_NEEDED_TAILROOM.
Instead the actual values are read from CAIF Link Layer device
and calculated.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
drivers/net/caif/caif_serial.c | 2 +-
include/net/caif/caif_dev.h | 8 ++++-
include/net/caif/caif_layer.h | 6 ----
include/net/caif/cfcnfg.h | 16 ++++++++--
net/caif/caif_dev.c | 12 +++++--
net/caif/caif_socket.c | 54 +++++++++++++++++++++++------------
net/caif/cfcnfg.c | 39 +++++++++++++++++++++++--
net/caif/cfctrl.c | 11 ++----
net/caif/cfpkt_skbuff.c | 4 +-
net/caif/cfrfml.c | 5 ---
net/caif/cfserl.c | 7 ++--
net/caif/cfutill.c | 6 ----
net/caif/cfveil.c | 5 ---
net/caif/chnl_net.c | 61 ++++++++++++++++++++++++++++++++-------
14 files changed, 159 insertions(+), 77 deletions(-)
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 09257ca..8cd424e 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -62,6 +62,7 @@ static int caif_net_open(struct net_device *dev);
static int caif_net_close(struct net_device *dev);
struct ser_device {
+ /* caif_dev_common MUST be first element in dev private data */
struct caif_dev_common common;
struct list_head node;
struct net_device *dev;
@@ -396,7 +397,6 @@ static void caifdev_setup(struct net_device *dev)
dev->type = ARPHRD_CAIF;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = CAIF_MAX_MTU;
- dev->hard_header_len = CAIF_NEEDED_HEADROOM;
dev->tx_queue_len = 0;
dev->destructor = free_netdev;
skb_queue_head_init(&serdev->head);
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index 318ab94..6da573c 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -50,6 +50,9 @@ struct caif_connect_request {
* @client_layer: User implementation of client layer. This layer
* MUST have receive and control callback functions
* implemented.
+ * @ifindex: Link layer interface index used for this connection.
+ * @headroom: Head room needed by CAIF protocol.
+ * @tailroom: Tail room needed by CAIF protocol.
*
* This function connects a CAIF channel. The Client must implement
* the struct cflayer. This layer represents the Client layer and holds
@@ -59,8 +62,9 @@ struct caif_connect_request {
* E.g. CAIF Socket will call this function for each socket it connects
* and have one client_layer instance for each socket.
*/
-int caif_connect_client(struct caif_connect_request *config,
- struct cflayer *client_layer);
+int caif_connect_client(struct caif_connect_request *conn_req,
+ struct cflayer *client_layer, int *ifindex,
+ int *headroom, int *tailroom);
/**
* caif_disconnect_client - Disconnects a client from the CAIF stack.
diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h
index 25c472f..c8b07a9 100644
--- a/include/net/caif/caif_layer.h
+++ b/include/net/caif/caif_layer.h
@@ -15,14 +15,8 @@ struct cfpktq;
struct caif_payload_info;
struct caif_packet_funcs;
-#define CAIF_MAX_FRAMESIZE 4096
-#define CAIF_MAX_PAYLOAD_SIZE (4096 - 64)
-#define CAIF_NEEDED_HEADROOM (10)
-#define CAIF_NEEDED_TAILROOM (2)
#define CAIF_LAYER_NAME_SZ 16
-#define CAIF_SUCCESS 1
-#define CAIF_FAILURE 0
/**
* caif_assert() - Assert function for CAIF.
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index 9fc2fc2..bd646fa 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -7,6 +7,7 @@
#ifndef CFCNFG_H_
#define CFCNFG_H_
#include <linux/spinlock.h>
+#include <linux/netdevice.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfctrl.h>
@@ -73,8 +74,8 @@ void cfcnfg_remove(struct cfcnfg *cfg);
void
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
- void *dev, struct cflayer *phy_layer, u16 *phyid,
- enum cfcnfg_phy_preference pref,
+ struct net_device *dev, struct cflayer *phy_layer,
+ u16 *phyid, enum cfcnfg_phy_preference pref,
bool fcs, bool stx);
/**
@@ -114,11 +115,18 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer);
* @param: Link setup parameters.
* @adap_layer: Specify the adaptation layer; the receive and
* flow-control functions MUST be set in the structure.
- *
+ * @ifindex: Link layer interface index used for this connection.
+ * @proto_head: Protocol head-space needed by CAIF protocol,
+ * excluding link layer.
+ * @proto_tail: Protocol tail-space needed by CAIF protocol,
+ * excluding link layer.
*/
int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
struct cfctrl_link_param *param,
- struct cflayer *adap_layer);
+ struct cflayer *adap_layer,
+ int *ifindex,
+ int *proto_head,
+ int *proto_tail);
/**
* cfcnfg_get_phyid() - Get physical ID, given type.
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index e2b86f1..0b586e9 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -255,7 +255,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
pref = CFPHYPREF_HIGH_BW;
break;
}
-
+ dev_hold(dev);
cfcnfg_add_phy_layer(get_caif_conf(),
phy_type,
dev,
@@ -285,6 +285,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
caifd->layer.up->ctrlcmd(caifd->layer.up,
_CAIF_CTRLCMD_PHYIF_DOWN_IND,
caifd->layer.id);
+ might_sleep();
res = wait_event_interruptible_timeout(caifd->event,
atomic_read(&caifd->in_use) == 0,
TIMEOUT);
@@ -300,6 +301,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
"Unregistering an active CAIF device: %s\n",
__func__, dev->name);
cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer);
+ dev_put(dev);
atomic_set(&caifd->state, what);
break;
@@ -326,7 +328,8 @@ struct cfcnfg *get_caif_conf(void)
EXPORT_SYMBOL(get_caif_conf);
int caif_connect_client(struct caif_connect_request *conn_req,
- struct cflayer *client_layer)
+ struct cflayer *client_layer, int *ifindex,
+ int *headroom, int *tailroom)
{
struct cfctrl_link_param param;
int ret;
@@ -334,8 +337,9 @@ int caif_connect_client(struct caif_connect_request *conn_req,
if (ret)
return ret;
/* Hook up the adaptation layer. */
- return cfcnfg_add_adaptation_layer(get_caif_conf(),
- ¶m, client_layer);
+ return cfcnfg_add_adaptation_layer(get_caif_conf(), ¶m,
+ client_layer, ifindex,
+ headroom, tailroom);
}
EXPORT_SYMBOL(caif_connect_client);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 15fab8b..2c2f7d7 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -28,8 +28,8 @@
MODULE_LICENSE("GPL");
MODULE_ALIAS_NETPROTO(AF_CAIF);
-#define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10)
-#define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100)
+#define CAIF_DEF_SNDBUF (4096*10)
+#define CAIF_DEF_RCVBUF (4096*100)
/*
* CAIF state is re-using the TCP socket states.
@@ -76,6 +76,7 @@ struct caifsock {
struct caif_connect_request conn_req;
struct mutex readlock;
struct dentry *debugfs_socket_dir;
+ int headroom, tailroom, maxframe;
};
static int rx_flow_is_on(struct caifsock *cf_sk)
@@ -287,6 +288,7 @@ static void caif_check_flow_release(struct sock *sk)
if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL)
return;
+
if (rx_flow_is_on(cf_sk))
return;
@@ -598,27 +600,31 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto err;
noblock = msg->msg_flags & MSG_DONTWAIT;
- buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM;
-
- ret = -EMSGSIZE;
- if (buffer_size > CAIF_MAX_PAYLOAD_SIZE)
- goto err;
-
timeo = sock_sndtimeo(sk, noblock);
timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk),
1, timeo, &ret);
+ if (ret)
+ goto err;
ret = -EPIPE;
if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
sock_flag(sk, SOCK_DEAD) ||
(sk->sk_shutdown & RCV_SHUTDOWN))
goto err;
+ ret = -EMSGSIZE;
+ if (len > cf_sk->maxframe)
+ goto err;
+
+ buffer_size = len + cf_sk->headroom + cf_sk->tailroom;
+
ret = -ENOMEM;
skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret);
- if (!skb)
+
+ if (!skb || skb_tailroom(skb) < buffer_size)
goto err;
- skb_reserve(skb, CAIF_NEEDED_HEADROOM);
+
+ skb_reserve(skb, cf_sk->headroom);
ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
@@ -648,8 +654,6 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
int sent = 0;
long timeo;
- err = -EOPNOTSUPP;
-
if (unlikely(msg->msg_flags&MSG_OOB))
goto out_err;
@@ -666,8 +670,8 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = len-sent;
- if (size > CAIF_MAX_PAYLOAD_SIZE)
- size = CAIF_MAX_PAYLOAD_SIZE;
+ if (size > cf_sk->maxframe)
+ size = cf_sk->maxframe;
/* If size is more than half of sndbuf, chop up message */
if (size > ((sk->sk_sndbuf >> 1) - 64))
@@ -677,14 +681,14 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = SKB_MAX_ALLOC;
skb = sock_alloc_send_skb(sk,
- size + CAIF_NEEDED_HEADROOM
- + CAIF_NEEDED_TAILROOM,
+ size + cf_sk->headroom +
+ cf_sk->tailroom,
msg->msg_flags&MSG_DONTWAIT,
&err);
if (skb == NULL)
goto out_err;
- skb_reserve(skb, CAIF_NEEDED_HEADROOM);
+ skb_reserve(skb, cf_sk->headroom);
/*
* If you pass two values to the sock_alloc_send_skb
* it tries to grab the large buffer with GFP_NOFS
@@ -825,6 +829,9 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
long timeo;
int err;
+ int ifindex, headroom, tailroom;
+ struct net_device *dev;
+
lock_sock(sk);
err = -EAFNOSUPPORT;
@@ -887,12 +894,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
dbfs_atomic_inc(&cnt.num_connect_req);
cf_sk->layer.receive = caif_sktrecv_cb;
err = caif_connect_client(&cf_sk->conn_req,
- &cf_sk->layer);
+ &cf_sk->layer, &ifindex, &headroom, &tailroom);
if (err < 0) {
cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
cf_sk->sk.sk_state = CAIF_DISCONNECTED;
goto out;
}
+ dev = dev_get_by_index(sock_net(sk), ifindex);
+ cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom);
+ cf_sk->tailroom = tailroom;
+ cf_sk->maxframe = dev->mtu - (cf_sk->headroom + cf_sk->tailroom);
+ dev_put(dev);
+ if (cf_sk->maxframe < 1) {
+ pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n",
+ __func__, dev->mtu);
+ err = -ENODEV;
+ goto out;
+ }
err = -EINPROGRESS;
wait_connect:
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index df43f26..ca4077c 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/slab.h>
+#include <linux/netdevice.h>
#include <net/caif/caif_layer.h>
#include <net/caif/cfpkt.h>
#include <net/caif/cfcnfg.h>
@@ -41,6 +42,15 @@ struct cfcnfg_phyinfo {
/* Information about the physical device */
struct dev_info dev_info;
+
+ /* Interface index */
+ int ifindex;
+
+ /* Use Start of frame extension */
+ bool use_stx;
+
+ /* Use Start of frame checksum */
+ bool use_fcs;
};
struct cfcnfg {
@@ -248,9 +258,20 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
{
}
+int protohead[CFCTRL_SRV_MASK] = {
+ [CFCTRL_SRV_VEI] = 4,
+ [CFCTRL_SRV_DATAGRAM] = 7,
+ [CFCTRL_SRV_UTIL] = 4,
+ [CFCTRL_SRV_RFM] = 3,
+ [CFCTRL_SRV_DBG] = 3,
+};
+
int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
struct cfctrl_link_param *param,
- struct cflayer *adap_layer)
+ struct cflayer *adap_layer,
+ int *ifindex,
+ int *proto_head,
+ int *proto_tail)
{
struct cflayer *frml;
if (adap_layer == NULL) {
@@ -276,6 +297,14 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
param->phyid);
caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id ==
param->phyid);
+
+ *ifindex = cnfg->phy_layers[param->phyid].ifindex;
+ *proto_head =
+ protohead[param->linktype]+
+ (cnfg->phy_layers[param->phyid].use_stx ? 1 : 0);
+
+ *proto_tail = 2;
+
/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
cfctrl_enum_req(cnfg->ctrl, param->phyid);
return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
@@ -363,8 +392,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
void
cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
- void *dev, struct cflayer *phy_layer, u16 *phyid,
- enum cfcnfg_phy_preference pref,
+ struct net_device *dev, struct cflayer *phy_layer,
+ u16 *phyid, enum cfcnfg_phy_preference pref,
bool fcs, bool stx)
{
struct cflayer *frml;
@@ -418,6 +447,10 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
cnfg->phy_layers[*phyid].dev_info.dev = dev;
cnfg->phy_layers[*phyid].phy_layer = phy_layer;
cnfg->phy_layers[*phyid].phy_ref_count = 0;
+ cnfg->phy_layers[*phyid].ifindex = dev->ifindex;
+ cnfg->phy_layers[*phyid].use_stx = stx;
+ cnfg->phy_layers[*phyid].use_fcs = fcs;
+
phy_layer->type = phy_type;
frml = cffrml_create(*phyid, fcs);
if (!frml) {
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index fcfda98..9501cfd 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -19,7 +19,7 @@
#ifdef CAIF_NO_LOOP
static int handle_loop(struct cfctrl *ctrl,
int cmd, struct cfpkt *pkt){
- return CAIF_FAILURE;
+ return -1;
}
#else
static int handle_loop(struct cfctrl *ctrl,
@@ -132,7 +132,7 @@ struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
if (cfctrl_req_eq(req, p)) {
if (p != first)
- pr_warning("CAIF: %s(): Requests are not "
+ pr_debug("CAIF: %s(): Requests are not "
"received in order\n",
__func__);
@@ -364,12 +364,9 @@ void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
struct cfctrl_request_info *p, *tmp;
struct cfctrl *ctrl = container_obj(layr);
spin_lock(&ctrl->info_list_lock);
- pr_warning("CAIF: %s(): enter\n", __func__);
list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
if (p->client_layer == adap_layer) {
- pr_warning("CAIF: %s(): cancel req :%d\n", __func__,
- p->sequence_no);
list_del(&p->list);
kfree(p);
}
@@ -395,7 +392,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
cmd = cmdrsp & CFCTRL_CMD_MASK;
if (cmd != CFCTRL_CMD_LINK_ERR
&& CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
- if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE)
+ if (handle_loop(cfctrl, cmd, pkt) < 0)
cmdrsp |= CFCTRL_ERR_BIT;
}
@@ -647,6 +644,6 @@ found:
default:
break;
}
- return CAIF_SUCCESS;
+ return 0;
}
#endif
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index a6fdf89..c419588 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -9,8 +9,8 @@
#include <linux/hardirq.h>
#include <net/caif/cfpkt.h>
-#define PKT_PREFIX CAIF_NEEDED_HEADROOM
-#define PKT_POSTFIX CAIF_NEEDED_TAILROOM
+#define PKT_PREFIX 10
+#define PKT_POSTFIX 2
#define PKT_LEN_WHEN_EXTENDING 128
#define PKT_ERROR(pkt, errmsg) do { \
cfpkt_priv(pkt)->erronous = true; \
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c
index cd2830f..b46b5f1 100644
--- a/net/caif/cfrfml.c
+++ b/net/caif/cfrfml.c
@@ -83,11 +83,6 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
if (!cfsrvl_ready(service, &ret))
return ret;
- if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
- pr_err("CAIF: %s():Packet too large - size=%d\n",
- __func__, cfpkt_getlen(pkt));
- return -EOVERFLOW;
- }
if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
return -EPROTO;
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index cb4325a..1ea484f 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -14,7 +14,8 @@
#define container_obj(layr) ((struct cfserl *) layr)
#define CFSERL_STX 0x02
-#define CAIF_MINIUM_PACKET_SIZE 4
+#define SERIAL_MINIUM_PACKET_SIZE 4
+#define SERIAL_MAX_FRAMESIZE 4096
struct cfserl {
struct cflayer layer;
struct cfpkt *incomplete_frm;
@@ -117,8 +118,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
/*
* Frame error handling
*/
- if (expectlen < CAIF_MINIUM_PACKET_SIZE
- || expectlen > CAIF_MAX_FRAMESIZE) {
+ if (expectlen < SERIAL_MINIUM_PACKET_SIZE
+ || expectlen > SERIAL_MAX_FRAMESIZE) {
if (!layr->usestx) {
if (pkt != NULL)
cfpkt_destroy(pkt);
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c
index 5fd2c9e..5d55345 100644
--- a/net/caif/cfutill.c
+++ b/net/caif/cfutill.c
@@ -90,12 +90,6 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt)
if (!cfsrvl_ready(service, &ret))
return ret;
- if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
- pr_err("CAIF: %s(): packet too large size=%d\n",
- __func__, cfpkt_getlen(pkt));
- return -EOVERFLOW;
- }
-
cfpkt_add_head(pkt, &zero, 1);
/* Add info for MUX-layer to route the packet out. */
info = cfpkt_info(pkt);
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 0fd827f..cfac80a 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -84,11 +84,6 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
return ret;
caif_assert(layr->dn != NULL);
caif_assert(layr->dn->transmit != NULL);
- if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
- pr_warning("CAIF: %s(): Packet too large - size=%d\n",
- __func__, cfpkt_getlen(pkt));
- return -EOVERFLOW;
- }
if (cfpkt_add_head(pkt, &tmp, 1) < 0) {
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 610966a..7de0342 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -23,7 +23,7 @@
#include <net/caif/caif_dev.h>
/* GPRS PDP connection has MTU to 1500 */
-#define SIZE_MTU 1500
+#define GPRS_PDP_MTU 1500
/* 5 sec. connect timeout */
#define CONNECT_TIMEOUT (5 * HZ)
#define CAIF_NET_DEFAULT_QUEUE_LEN 500
@@ -232,6 +232,8 @@ static int chnl_net_open(struct net_device *dev)
{
struct chnl_net *priv = NULL;
int result = -1;
+ int llifindex, headroom, tailroom, mtu;
+ struct net_device *lldev;
ASSERT_RTNL();
priv = netdev_priv(dev);
if (!priv) {
@@ -241,41 +243,80 @@ static int chnl_net_open(struct net_device *dev)
if (priv->state != CAIF_CONNECTING) {
priv->state = CAIF_CONNECTING;
- result = caif_connect_client(&priv->conn_req, &priv->chnl);
+ result = caif_connect_client(&priv->conn_req, &priv->chnl,
+ &llifindex, &headroom, &tailroom);
if (result != 0) {
- priv->state = CAIF_DISCONNECTED;
pr_debug("CAIF: %s(): err: "
"Unable to register and open device,"
" Err:%d\n",
__func__,
result);
- return result;
+ goto error;
+ }
+
+ lldev = dev_get_by_index(dev_net(dev), llifindex);
+
+ if (lldev == NULL) {
+ pr_debug("CAIF: %s(): no interface?\n", __func__);
+ result = -ENODEV;
+ goto error;
+ }
+ /*
+ * MTU, head-room etc is not know before we have a
+ * CAIF link layer device available. MTU calculation may
+ * override initial RTNL configuration.
+ * GPRS PDP Context defines 1500 bytes as MTU.
+ */
+ dev->needed_headroom = headroom + lldev->needed_headroom;
+ dev->needed_tailroom = tailroom + lldev->needed_tailroom;
+ dev->hard_header_len = headroom + lldev->hard_header_len;
+ mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom));
+ mtu = min_t(int, GPRS_PDP_MTU, mtu);
+ dev_set_mtu(dev, mtu);
+ dev_put(lldev);
+
+ if (mtu < 100) {
+ pr_warning("CAIF: %s(): "
+ "CAIF Interface MTU too small (%d)\n",
+ __func__, mtu);
+ result = -ENODEV;
+ goto error;
}
}
result = wait_event_interruptible_timeout(priv->netmgmt_wq,
priv->state != CAIF_CONNECTING,
CONNECT_TIMEOUT);
-
if (result == -ERESTARTSYS) {
pr_debug("CAIF: %s(): wait_event_interruptible"
" woken by a signal\n", __func__);
- return -ERESTARTSYS;
+ result = -ERESTARTSYS;
+ goto error;
}
+
if (result == 0) {
pr_debug("CAIF: %s(): connect timeout\n", __func__);
caif_disconnect_client(&priv->chnl);
priv->state = CAIF_DISCONNECTED;
pr_debug("CAIF: %s(): state disconnected\n", __func__);
- return -ETIMEDOUT;
+ result = -ETIMEDOUT;
+ goto error;
}
if (priv->state != CAIF_CONNECTED) {
pr_debug("CAIF: %s(): connect failed\n", __func__);
- return -ECONNREFUSED;
+ result = -ECONNREFUSED;
+ goto error;
}
pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__);
return 0;
+
+error:
+ caif_disconnect_client(&priv->chnl);
+ priv->state = CAIF_DISCONNECTED;
+ pr_debug("CAIF: %s(): state disconnected\n", __func__);
+ return result;
+
}
static int chnl_net_stop(struct net_device *dev)
@@ -321,9 +362,7 @@ static void ipcaif_net_setup(struct net_device *dev)
dev->destructor = free_netdev;
dev->flags |= IFF_NOARP;
dev->flags |= IFF_POINTOPOINT;
- dev->needed_headroom = CAIF_NEEDED_HEADROOM;
- dev->needed_tailroom = CAIF_NEEDED_TAILROOM;
- dev->mtu = SIZE_MTU;
+ dev->mtu = GPRS_PDP_MTU;
dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN;
priv = netdev_priv(dev);
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 5/8] caif: Add debug connection type for CAIF.
From: sjur.brandeland @ 2010-05-20 7:44 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, linus.walleji, sjurbren,
Sjur Braendeland
In-Reply-To: <1274341448-14924-5-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Added new CAIF protocol type CAIFPROTO_DEBUG for accessing
CAIF debug on the ST Ericsson modems.
There are two debug servers on the modem, one for radio related
debug (CAIF_RADIO_DEBUG_SERVICE) and the other for
communication/application related debug (CAIF_COM_DEBUG_SERVICE).
The debug connection can contain trace debug printouts or
interactive debug used for debugging and test.
Debug connections can be of type STREAM or SEQPACKET.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/linux/caif/caif_socket.h | 40 +++++++++++++++++++++++++++++++++++++-
net/caif/caif_config_util.c | 5 ++++
net/caif/caif_socket.c | 5 ----
3 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/include/linux/caif/caif_socket.h b/include/linux/caif/caif_socket.h
index 2a61eb1..3e8851b 100644
--- a/include/linux/caif/caif_socket.h
+++ b/include/linux/caif/caif_socket.h
@@ -62,6 +62,7 @@ enum caif_channel_priority {
* @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing.
* @CAIFPROTO_UTIL: Utility (Psock) channel.
* @CAIFPROTO_RFM: Remote File Manager
+ * @CAIFPROTO_DEBUG: Debug link
*
* This enum defines the CAIF Channel type to be used. This defines
* the service to connect to on the modem.
@@ -72,6 +73,7 @@ enum caif_protocol_type {
CAIFPROTO_DATAGRAM_LOOP,
CAIFPROTO_UTIL,
CAIFPROTO_RFM,
+ CAIFPROTO_DEBUG,
_CAIFPROTO_MAX
};
#define CAIFPROTO_MAX _CAIFPROTO_MAX
@@ -85,6 +87,29 @@ enum caif_at_type {
};
/**
+ * enum caif_debug_type - Content selection for debug connection
+ * @CAIF_DEBUG_TRACE_INTERACTIVE: Connection will contain
+ * both trace and interactive debug.
+ * @CAIF_DEBUG_TRACE: Connection contains trace only.
+ * @CAIF_DEBUG_INTERACTIVE: Connection to interactive debug.
+ */
+enum caif_debug_type {
+ CAIF_DEBUG_TRACE_INTERACTIVE = 0,
+ CAIF_DEBUG_TRACE,
+ CAIF_DEBUG_INTERACTIVE,
+};
+
+/**
+ * enum caif_debug_service - Debug Service to connect.
+ * @CAIF_RADIO_DEBUG_SERVICE: Debug on the Radio sub-system
+ * @CAIF_COM_DEBUG_SERVICE: Debug on the communication sub-system
+ */
+enum caif_debug_service {
+ CAIF_RADIO_DEBUG_SERVICE = 1,
+ CAIF_COM_DEBUG_SERVICE
+};
+
+/**
* struct sockaddr_caif - the sockaddr structure for CAIF sockets.
* @family: Address family number, must be AF_CAIF.
* @u: Union of address data 'switched' by family.
@@ -107,7 +132,14 @@ enum caif_at_type {
*
* @u.rfm.connection_id: Connection ID for RFM.
*
- * @u.rfm.volume: Volume to mount.
+ * @u.rfm.volume: Volume to mount.
+ *
+ * @u.dbg: Applies when family = CAIFPROTO_DEBUG.
+ *
+ * @u.dbg.type: Type of debug connection to set up
+ * (caif_debug_type).
+ *
+ * @u.dbg.service: Service sub-system to connect *
*
* Description:
* This structure holds the connect parameters used for setting up a
@@ -130,6 +162,12 @@ struct sockaddr_caif {
__u32 connection_id;
char volume[16];
} rfm; /* CAIFPROTO_RFM */
+ struct {
+ __u8 type; /* type:enum
+ * caif_debug_type */
+ __u8 service; /* service:caif_debug_service */
+ } dbg; /* CAIFPROTO_DEBUG */
+
} u;
};
diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c
index 6f36580..76ae683 100644
--- a/net/caif/caif_config_util.c
+++ b/net/caif/caif_config_util.c
@@ -80,6 +80,11 @@ int connect_req_to_link_param(struct cfcnfg *cnfg,
l->u.utility.paramlen);
break;
+ case CAIFPROTO_DEBUG:
+ l->linktype = CFCTRL_SRV_DBG;
+ l->endpoint = s->sockaddr.u.dbg.service;
+ l->chtype = s->sockaddr.u.dbg.type;
+ break;
default:
return -EINVAL;
}
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 6d33de7..15fab8b 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -831,11 +831,6 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
if (uaddr->sa_family != AF_CAIF)
goto out;
- err = -ESOCKTNOSUPPORT;
- if (unlikely(!(sk->sk_type == SOCK_STREAM &&
- cf_sk->sk.sk_protocol == CAIFPROTO_AT) &&
- sk->sk_type != SOCK_SEQPACKET))
- goto out;
switch (sock->state) {
case SS_UNCONNECTED:
/* Normal case, a fresh connect */
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 4/8] caif: Add support for MSG_TRUNC.
From: sjur.brandeland @ 2010-05-20 7:44 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, linus.walleji, sjurbren,
Sjur Braendeland
In-Reply-To: <1274341448-14924-4-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changed handling when skb don't fit in user buffer,
instead of returning -EMSGSIZE, the buffer is truncated (just
as unix seqpakcet does).
Also MSG_TRUNC can be used to read out the actual packet size.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
net/caif/caif_socket.c | 42 +++++++++++++++---------------------------
1 files changed, 15 insertions(+), 27 deletions(-)
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 77e9956..6d33de7 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -297,59 +297,47 @@ static void caif_check_flow_release(struct sock *sk)
CAIF_MODEMCMD_FLOW_ON_REQ);
}
}
+
/*
* Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer
* has sufficient size.
*/
-
static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *m, size_t buf_len, int flags)
+ struct msghdr *m, size_t len, int flags)
{
struct sock *sk = sock->sk;
struct sk_buff *skb;
int ret = 0;
- int len;
+ int copylen;
- if (unlikely(!buf_len))
- return -EINVAL;
+ ret = -EOPNOTSUPP;
+ if (m->msg_flags&MSG_OOB)
+ goto read_error;
skb = skb_recv_datagram(sk, flags, 0 , &ret);
if (!skb)
goto read_error;
-
- len = skb->len;
-
- if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) {
- len = buf_len;
- /*
- * Push skb back on receive queue if buffer too small.
- * This has a built-in race where multi-threaded receive
- * may get packet in wrong order, but multiple read does
- * not really guarantee ordered delivery anyway.
- * Let's optimize for speed without taking locks.
- */
-
- skb_queue_head(&sk->sk_receive_queue, skb);
- ret = -EMSGSIZE;
- goto read_error;
+ copylen = skb->len;
+ if (len < copylen) {
+ m->msg_flags |= MSG_TRUNC;
+ copylen = len;
}
- ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
+ ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, copylen);
if (ret)
- goto read_error;
+ goto out_free;
+ ret = (flags & MSG_TRUNC) ? skb->len : copylen;
+out_free:
skb_free_datagram(sk, skb);
-
caif_check_flow_release(sk);
-
- return len;
+ return ret;
read_error:
return ret;
}
-
/* Copied from unix_stream_wait_data, identical except for lock call. */
static long caif_stream_data_wait(struct sock *sk, long timeo)
{
--
1.6.3.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox