static int
dp_xmit_skb_finish(struct sk_buff *skb)
{
- /* The ip_fragment function does not copy the Ethernet header into
- * the newly generated frames, so put back the values stowed
- * earlier. */
- if (snat_copy_header(skb)) {
+ /* Copy back the Ethernet header that was stowed earlier. */
+ if (skb->protocol == htons(ETH_P_IP) && snat_copy_header(skb)) {
kfree_skb(skb);
return -EINVAL;
}
skb_pull(skb, ETH_HLEN);
+ /* The ip_fragment function does not copy the Ethernet header into
+ * the newly generated frames, so stow the original. */
+ if (skb->protocol == htons(ETH_P_IP))
+ snat_save_header(skb);
+
if (skb->protocol == htons(ETH_P_IP) &&
skb->len > skb->dev->mtu &&
!skb_is_gso(skb)) {
}
/* Save a copy of the original Ethernet header. */
-static inline void snat_save_header(struct sk_buff *skb)
+void snat_save_header(struct sk_buff *skb)
{
int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
+ if (!skb->nf_bridge)
+ return;
+
skb_copy_from_linear_data_offset(skb, -header_size,
skb->nf_bridge->data, header_size);
}
/* Pass the translated packet as input to the OpenFlow stack, which
* consumes it. */
- snat_save_header(skb);
skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
fwd_port_input(p->dp->chain, skb, p);
void snat_local_in(struct sk_buff *skb);
int snat_pre_route(struct sk_buff *skb);
void snat_skb(struct datapath *dp, const struct sk_buff *skb, int out_port);
+void snat_save_header(struct sk_buff *skb);
int snat_copy_header(struct sk_buff *skb);
void snat_maint(struct net_bridge_port *p);
int snat_mod_config(struct datapath *, const struct nx_act_config *);