title: Linux kernel: packet is forwarded to another interface, but isn't sent onwards
body: <p>I've made a <code>virtual network interface</code> that forwards any <code>packet</code> it receives to a physical interface <code>eth2</code>, with the intention of sending it to whichever destination is required.</p>
  
  <p>The virtual interface's <code>hard_start_xmit</code> function receives the packet, changes the source<code>MAC and IP</code>, sets the handling device to be the physical interface, and sets the packet type to <code>PACKET_OUTGOING</code>.</p>
  
  <pre><code>static int forward_packet(struct sk_buff *skb, struct net_device *dev) {
      char switched_device_name[] = "eth2";
      struct net_device *switched_device = dev_get_by_name(switched_device_name);
      int ifrx_output;
      u32 switched_device_ip;
  
      if (!switched_device) {
          printk("Error: Couldn't get device %s for switching.\n", switched_device_name);
          return -1;
      }
  
      skb-&gt;dev = switched_device;
      skb-&gt;input_dev = switched_device;
      skb-&gt;pkt_type = PACKET_OUTGOING;
  
      switched_device_ip = get_interface_ip(switched_device);
      change_source_mac_and_ip(skb, switched_device-&gt;dev_addr, switched_device_ip);
  
      ifrx_output = netif_rx(skb);
      printk("netif_rx returned %d.\n", ifrx_output);
      return 0;
  }
  </code></pre>
  
  <p>I tested this code, and while the packet does appear in the physical interface's <code>tcpdump</code>, there's no trace of it in the destination machine.</p>
  
  <p>The only reason I can think something like this would happen is because the physical interface treats it as an incoming packet with no need to pass it on. However as far as I can tell, only <code>skb-&gt;pkt_type</code> determines that.</p>
  
  <p>What other packet changes could I be missing?</p>