|
@@ -269,6 +269,14 @@ static void eoib_rx_av ( struct eoib_device *eoib, const uint8_t *mac,
|
269
|
269
|
return;
|
270
|
270
|
}
|
271
|
271
|
|
|
272
|
+ /* Some dubious EoIB implementations utilise an Ethernet-to-
|
|
273
|
+ * EoIB gateway that will send packets from the wrong QPN.
|
|
274
|
+ */
|
|
275
|
+ if ( eoib_has_gateway ( eoib ) &&
|
|
276
|
+ ( memcmp ( gid, &eoib->gateway.gid, sizeof ( *gid ) ) == 0 ) ) {
|
|
277
|
+ qpn = eoib->gateway.qpn;
|
|
278
|
+ }
|
|
279
|
+
|
272
|
280
|
/* Do nothing if peer cache entry is complete and correct */
|
273
|
281
|
if ( ( peer->av.lid == av->lid ) && ( peer->av.qpn == qpn ) ) {
|
274
|
282
|
DBGCP ( eoib, "EoIB %s %s RX unchanged\n",
|
|
@@ -326,9 +334,14 @@ static int eoib_transmit ( struct net_device *netdev,
|
326
|
334
|
if ( iob_len ( iobuf ) < zlen )
|
327
|
335
|
iob_pad ( iobuf, zlen );
|
328
|
336
|
|
329
|
|
- /* If we have no unicast address then send as a broadcast */
|
330
|
|
- if ( ! av )
|
|
337
|
+ /* If we have no unicast address then send as a broadcast,
|
|
338
|
+ * with a duplicate sent to the gateway if applicable.
|
|
339
|
+ */
|
|
340
|
+ if ( ! av ) {
|
331
|
341
|
av = &eoib->broadcast;
|
|
342
|
+ if ( eoib_has_gateway ( eoib ) )
|
|
343
|
+ eoib->duplicate ( eoib, iobuf );
|
|
344
|
+ }
|
332
|
345
|
|
333
|
346
|
/* Post send work queue entry */
|
334
|
347
|
return ib_post_send ( eoib->ibdev, eoib->qp, av, iobuf );
|
|
@@ -797,3 +810,86 @@ struct net_protocol eoib_heartbeat_protocol __net_protocol = {
|
797
|
810
|
.rx = eoib_heartbeat_rx,
|
798
|
811
|
.ntoa = eoib_heartbeat_ntoa,
|
799
|
812
|
};
|
|
813
|
+
|
|
814
|
+/****************************************************************************
|
|
815
|
+ *
|
|
816
|
+ * EoIB gateway
|
|
817
|
+ *
|
|
818
|
+ ****************************************************************************
|
|
819
|
+ *
|
|
820
|
+ * Some dubious EoIB implementations require all broadcast traffic to
|
|
821
|
+ * be sent twice: once to the actual broadcast group, and once as a
|
|
822
|
+ * unicast to the EoIB-to-Ethernet gateway. This somewhat curious
|
|
823
|
+ * design arises since the EoIB-to-Ethernet gateway hardware lacks the
|
|
824
|
+ * ability to attach a queue pair to a multicast GID (or LID), and so
|
|
825
|
+ * cannot receive traffic sent to the broadcast group.
|
|
826
|
+ *
|
|
827
|
+ */
|
|
828
|
+
|
|
829
|
+/**
|
|
830
|
+ * Transmit duplicate packet to the EoIB gateway
|
|
831
|
+ *
|
|
832
|
+ * @v eoib EoIB device
|
|
833
|
+ * @v original Original I/O buffer
|
|
834
|
+ */
|
|
835
|
+static void eoib_duplicate ( struct eoib_device *eoib,
|
|
836
|
+ struct io_buffer *original ) {
|
|
837
|
+ struct net_device *netdev = eoib->netdev;
|
|
838
|
+ struct ib_device *ibdev = eoib->ibdev;
|
|
839
|
+ struct ib_address_vector *av = &eoib->gateway;
|
|
840
|
+ size_t len = iob_len ( original );
|
|
841
|
+ struct io_buffer *copy;
|
|
842
|
+ int rc;
|
|
843
|
+
|
|
844
|
+ /* Create copy of I/O buffer */
|
|
845
|
+ copy = alloc_iob ( len );
|
|
846
|
+ if ( ! copy ) {
|
|
847
|
+ rc = -ENOMEM;
|
|
848
|
+ goto err_alloc;
|
|
849
|
+ }
|
|
850
|
+ memcpy ( iob_put ( copy, len ), original->data, len );
|
|
851
|
+
|
|
852
|
+ /* Append to network device's transmit queue */
|
|
853
|
+ list_add_tail ( ©->list, &original->list );
|
|
854
|
+
|
|
855
|
+ /* Resolve path to gateway */
|
|
856
|
+ if ( ( rc = ib_resolve_path ( ibdev, av ) ) != 0 ) {
|
|
857
|
+ DBGC ( eoib, "EoIB %s no path to gateway: %s\n",
|
|
858
|
+ eoib->name, strerror ( rc ) );
|
|
859
|
+ goto err_path;
|
|
860
|
+ }
|
|
861
|
+
|
|
862
|
+ /* Force use of GRH even for local destinations */
|
|
863
|
+ av->gid_present = 1;
|
|
864
|
+
|
|
865
|
+ /* Post send work queue entry */
|
|
866
|
+ if ( ( rc = ib_post_send ( eoib->ibdev, eoib->qp, av, copy ) ) != 0 )
|
|
867
|
+ goto err_post_send;
|
|
868
|
+
|
|
869
|
+ return;
|
|
870
|
+
|
|
871
|
+ err_post_send:
|
|
872
|
+ err_path:
|
|
873
|
+ err_alloc:
|
|
874
|
+ netdev_tx_complete_err ( netdev, copy, rc );
|
|
875
|
+}
|
|
876
|
+
|
|
877
|
+/**
|
|
878
|
+ * Set EoIB gateway
|
|
879
|
+ *
|
|
880
|
+ * @v eoib EoIB device
|
|
881
|
+ * @v av Address vector, or NULL to clear gateway
|
|
882
|
+ */
|
|
883
|
+void eoib_set_gateway ( struct eoib_device *eoib,
|
|
884
|
+ struct ib_address_vector *av ) {
|
|
885
|
+
|
|
886
|
+ if ( av ) {
|
|
887
|
+ DBGC ( eoib, "EoIB %s using gateway " IB_GID_FMT "\n",
|
|
888
|
+ eoib->name, IB_GID_ARGS ( &av->gid ) );
|
|
889
|
+ memcpy ( &eoib->gateway, av, sizeof ( eoib->gateway ) );
|
|
890
|
+ eoib->duplicate = eoib_duplicate;
|
|
891
|
+ } else {
|
|
892
|
+ DBGC ( eoib, "EoIB %s not using gateway\n", eoib->name );
|
|
893
|
+ eoib->duplicate = NULL;
|
|
894
|
+ }
|
|
895
|
+}
|