return skb;
}
-static inline unsigned packet_length(const struct sk_buff *skb)
-{
- unsigned length = skb->len - ETH_HLEN;
- if (skb->protocol == htons(ETH_P_8021Q))
- length -= VLAN_HLEN;
- return length;
-}
-
static void
do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
{
struct dp_port *p;
- int mtu;
if (!skb)
goto error;
if (!p)
goto error;
- mtu = vport_get_mtu(p->vport);
- if (packet_length(skb) > mtu && !skb_is_gso(skb)) {
- printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n",
- dp_name(dp), packet_length(skb), mtu);
- goto error;
- }
-
vport_send(p->vport, skb);
return;
#include <linux/dcache.h>
#include <linux/etherdevice.h>
#include <linux/if.h>
+#include <linux/if_vlan.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mutex.h>
dp_process_received_packet(dp_port, skb);
}
+static inline unsigned
+packet_length(const struct sk_buff *skb)
+{
+ unsigned length = skb->len - ETH_HLEN;
+
+ if (skb->protocol == htons(ETH_P_8021Q))
+ length -= VLAN_HLEN;
+
+ return length;
+}
+
/**
* vport_send - send a packet on a device
*
vport_send(struct vport *vport, struct sk_buff *skb)
{
int *loop_count;
+ int mtu;
int sent;
loop_count = &per_cpu_ptr(vport_loop_counter, get_cpu())->count[!!in_interrupt()];
(*loop_count)++;
- if (likely(*loop_count <= VPORT_MAX_LOOPS)) {
- sent = vport->ops->send(vport, skb);
- } else {
+ if (unlikely(*loop_count > VPORT_MAX_LOOPS)) {
if (net_ratelimit())
printk(KERN_WARNING "%s: dropping packet that has looped more than %d times\n",
dp_name(vport_get_dp_port(vport)->dp), VPORT_MAX_LOOPS);
+ goto error;
+ }
- sent = 0;
- kfree_skb(skb);
- vport_record_error(vport, VPORT_E_TX_DROPPED);
+ mtu = vport_get_mtu(vport);
+ if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n",
+ dp_name(vport_get_dp_port(vport)->dp), packet_length(skb), mtu);
+ goto error;
}
- (*loop_count)--;
- put_cpu();
+ sent = vport->ops->send(vport, skb);
if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
struct vport_percpu_stats *stats;
local_bh_enable();
}
+ goto out;
+
+error:
+ sent = 0;
+ kfree_skb(skb);
+ vport_record_error(vport, VPORT_E_TX_DROPPED);
+out:
+ (*loop_count)--;
+ put_cpu();
+
return sent;
}