aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r--drivers/net/macvlan.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ae2b5c79c55e..1e7faf9e87b2 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -116,42 +116,58 @@ static int macvlan_addr_busy(const struct macvlan_port *port,
116 return 0; 116 return 0;
117} 117}
118 118
119static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
120 unsigned int len, bool success,
121 bool multicast)
122{
123 struct macvlan_rx_stats *rx_stats;
124
125 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
126 if (likely(success)) {
127 rx_stats->rx_packets++;;
128 rx_stats->rx_bytes += len;
129 if (multicast)
130 rx_stats->multicast++;
131 } else {
132 rx_stats->rx_errors++;
133 }
134}
135
136static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev,
137 const struct ethhdr *eth)
138{
139 if (!skb)
140 return NET_RX_DROP;
141
142 skb->dev = dev;
143 if (!compare_ether_addr_64bits(eth->h_dest,
144 dev->broadcast))
145 skb->pkt_type = PACKET_BROADCAST;
146 else
147 skb->pkt_type = PACKET_MULTICAST;
148
149 return netif_rx(skb);
150}
151
119static void macvlan_broadcast(struct sk_buff *skb, 152static void macvlan_broadcast(struct sk_buff *skb,
120 const struct macvlan_port *port) 153 const struct macvlan_port *port)
121{ 154{
122 const struct ethhdr *eth = eth_hdr(skb); 155 const struct ethhdr *eth = eth_hdr(skb);
123 const struct macvlan_dev *vlan; 156 const struct macvlan_dev *vlan;
124 struct hlist_node *n; 157 struct hlist_node *n;
125 struct net_device *dev;
126 struct sk_buff *nskb; 158 struct sk_buff *nskb;
127 unsigned int i; 159 unsigned int i;
128 struct macvlan_rx_stats *rx_stats; 160 int err;
129 161
130 if (skb->protocol == htons(ETH_P_PAUSE)) 162 if (skb->protocol == htons(ETH_P_PAUSE))
131 return; 163 return;
132 164
133 for (i = 0; i < MACVLAN_HASH_SIZE; i++) { 165 for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
134 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { 166 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
135 dev = vlan->dev;
136 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id());
137
138 nskb = skb_clone(skb, GFP_ATOMIC); 167 nskb = skb_clone(skb, GFP_ATOMIC);
139 if (nskb == NULL) { 168 err = macvlan_broadcast_one(nskb, vlan->dev, eth);
140 rx_stats->rx_errors++; 169 macvlan_count_rx(vlan, skb->len + ETH_HLEN,
141 continue; 170 err == NET_RX_SUCCESS, 1);
142 }
143
144 rx_stats->rx_bytes += skb->len + ETH_HLEN;
145 rx_stats->rx_packets++;
146 rx_stats->multicast++;
147
148 nskb->dev = dev;
149 if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast))
150 nskb->pkt_type = PACKET_BROADCAST;
151 else
152 nskb->pkt_type = PACKET_MULTICAST;
153
154 netif_rx(nskb);
155 } 171 }
156 } 172 }
157} 173}
@@ -163,7 +179,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
163 const struct macvlan_port *port; 179 const struct macvlan_port *port;
164 const struct macvlan_dev *vlan; 180 const struct macvlan_dev *vlan;
165 struct net_device *dev; 181 struct net_device *dev;
166 struct macvlan_rx_stats *rx_stats; 182 unsigned int len;
167 183
168 port = rcu_dereference(skb->dev->macvlan_port); 184 port = rcu_dereference(skb->dev->macvlan_port);
169 if (port == NULL) 185 if (port == NULL)
@@ -183,15 +199,11 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
183 kfree_skb(skb); 199 kfree_skb(skb);
184 return NULL; 200 return NULL;
185 } 201 }
186 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); 202 len = skb->len + ETH_HLEN;
187 skb = skb_share_check(skb, GFP_ATOMIC); 203 skb = skb_share_check(skb, GFP_ATOMIC);
188 if (skb == NULL) { 204 macvlan_count_rx(vlan, len, skb != NULL, 0);
189 rx_stats->rx_errors++; 205 if (!skb)
190 return NULL; 206 return NULL;
191 }
192
193 rx_stats->rx_bytes += skb->len + ETH_HLEN;
194 rx_stats->rx_packets++;
195 207
196 skb->dev = dev; 208 skb->dev = dev;
197 skb->pkt_type = PACKET_HOST; 209 skb->pkt_type = PACKET_HOST;