diff options
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 70 |
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 | ||
119 | static 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 | |||
136 | static 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 | |||
119 | static void macvlan_broadcast(struct sk_buff *skb, | 152 | static 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; |