Index: src/csma/model/csma-channel.cc |
=================================================================== |
--- a/src/csma/model/csma-channel.cc |
+++ b/src/csma/model/csma-channel.cc |
@@ -1,6 +1,8 @@ |
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
/* |
* Copyright (c) 2007 Emmanuelle Laprise |
+ * Copyright (c) 2012 Jeff Young |
+ * Copyright (c) 2014 Murphy McCauley |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License version 2 as |
@@ -16,6 +18,8 @@ |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
* |
* Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca> |
+ * Author: Jeff Young <jyoung9@gatech.edu> |
+ * Author: Murphy McCauley <murphy.mccauley@gmail.com> |
*/ |
#include "csma-channel.h" |
@@ -45,6 +49,11 @@ |
TimeValue (Seconds (0)), |
MakeTimeAccessor (&CsmaChannel::m_delay), |
MakeTimeChecker ()) |
+ .AddAttribute ("FullDuplex", "Whether the channel is full duplex", |
+ TypeId::ATTR_CONSTRUCT, |
+ BooleanValue (false), |
+ MakeBooleanAccessor (&CsmaChannel::m_fullDuplex), |
+ MakeBooleanChecker ()) |
; |
return tid; |
} |
@@ -54,7 +63,6 @@ |
Channel () |
{ |
NS_LOG_FUNCTION_NOARGS (); |
- m_state = IDLE; |
m_deviceList.clear (); |
} |
@@ -70,9 +78,19 @@ |
NS_LOG_FUNCTION (this << device); |
NS_ASSERT (device != 0); |
+ // For full-duplex links we can only attach two devices to a channel |
+ // since there is no backoff |
+ if (m_fullDuplex && m_deviceList.size () > 2) |
Luciano Chaves
2016/02/24 16:03:05
To ensure that no more than two devices are attach
|
+ { |
+ NS_LOG_DEBUG ("Falling back to half-duplex"); |
+ m_fullDuplex = false; |
+ } |
+ |
CsmaDeviceRec rec (device); |
m_deviceList.push_back (rec); |
+ SetState (m_deviceList.size () - 1, IDLE); |
+ SetCurrentSrc (m_deviceList.size () - 1, m_deviceList.size () - 1); |
return (m_deviceList.size () - 1); |
} |
@@ -106,7 +124,7 @@ |
{ |
NS_LOG_FUNCTION (this << deviceId); |
- if (deviceId < m_deviceList.size ()) |
+ if (deviceId >= m_deviceList.size ()) |
{ |
return false; |
} |
@@ -137,7 +155,7 @@ |
m_deviceList[deviceId].active = false; |
- if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId)) |
+ if ((GetState (deviceId) == TRANSMITTING) && (GetCurrentSrc (deviceId) == deviceId)) |
{ |
NS_LOG_WARN ("CsmaChannel::Detach(): Device is currently" << "transmitting (" << deviceId << ")"); |
} |
@@ -174,7 +192,7 @@ |
NS_LOG_FUNCTION (this << p << srcId); |
NS_LOG_INFO ("UID is " << p->GetUid () << ")"); |
- if (m_state != IDLE) |
+ if (GetState (srcId) != IDLE) |
joao
2016/08/13 23:21:56
Can't a transmission start if there is some packet
Luciano Chaves
2016/08/15 18:00:25
Yeah, in full-duplex operation there is no need to
|
{ |
NS_LOG_WARN ("CsmaChannel::TransmitStart(): State is not IDLE"); |
return false; |
@@ -182,14 +200,14 @@ |
if (!IsActive (srcId)) |
{ |
- NS_LOG_ERROR ("CsmaChannel::TransmitStart(): Seclected source is not currently attached to network"); |
+ NS_LOG_ERROR ("CsmaChannel::TransmitStart(): Selected source is not currently attached to network"); |
return false; |
} |
NS_LOG_LOGIC ("switch to TRANSMITTING"); |
- m_currentPkt = p; |
- m_currentSrc = srcId; |
- m_state = TRANSMITTING; |
+ SetCurrentPkt (srcId, p); |
+ SetCurrentSrc (srcId, srcId); |
+ SetState (srcId, TRANSMITTING); |
return true; |
} |
@@ -200,17 +218,23 @@ |
} |
bool |
-CsmaChannel::TransmitEnd () |
+CsmaChannel::IsFullDuplex (void) const |
{ |
- NS_LOG_FUNCTION (this << m_currentPkt << m_currentSrc); |
- NS_LOG_INFO ("UID is " << m_currentPkt->GetUid () << ")"); |
+ return m_fullDuplex; |
+} |
- NS_ASSERT (m_state == TRANSMITTING); |
- m_state = PROPAGATING; |
+bool |
+CsmaChannel::TransmitEnd (uint32_t srcId) |
+{ |
+ NS_LOG_FUNCTION (this << GetCurrentPkt (srcId) << GetCurrentSrc (srcId)); |
+ NS_LOG_INFO ("UID is " << GetCurrentPkt (srcId)->GetUid () << ")"); |
+ |
+ NS_ASSERT (GetState (srcId) == TRANSMITTING); |
+ SetState (srcId, PROPAGATING); |
bool retVal = true; |
- if (!IsActive (m_currentSrc)) |
+ if (!IsActive (GetCurrentSrc (srcId))) |
{ |
NS_LOG_ERROR ("CsmaChannel::TransmitEnd(): Seclected source was detached before the end of the transmission"); |
retVal = false; |
@@ -225,31 +249,35 @@ |
uint32_t devId = 0; |
for (it = m_deviceList.begin (); it < m_deviceList.end (); it++) |
{ |
- if (it->IsActive ()) |
+ // In full duplex mode, don't deliver to sender |
+ if (!m_fullDuplex || (devId != GetCurrentSrc (srcId))) |
{ |
- // schedule reception events |
- Simulator::ScheduleWithContext (it->devicePtr->GetNode ()->GetId (), |
- m_delay, |
- &CsmaNetDevice::Receive, it->devicePtr, |
- m_currentPkt->Copy (), m_deviceList[m_currentSrc].devicePtr); |
+ if (it->IsActive ()) |
+ { |
+ // schedule reception events |
+ Simulator::ScheduleWithContext (it->devicePtr->GetNode ()->GetId (), |
+ m_delay, |
+ &CsmaNetDevice::Receive, it->devicePtr, |
+ GetCurrentPkt (srcId)->Copy (), m_deviceList[GetCurrentSrc (srcId)].devicePtr); |
+ } |
} |
devId++; |
} |
// also schedule for the tx side to go back to IDLE |
Simulator::Schedule (m_delay, &CsmaChannel::PropagationCompleteEvent, |
Luciano Chaves
2016/02/24 16:03:05
As indicated by Hugo at https://codereview.appspot
|
- this); |
+ this, srcId); |
return retVal; |
} |
void |
-CsmaChannel::PropagationCompleteEvent () |
+CsmaChannel::PropagationCompleteEvent (uint32_t deviceId) |
{ |
- NS_LOG_FUNCTION (this << m_currentPkt); |
- NS_LOG_INFO ("UID is " << m_currentPkt->GetUid () << ")"); |
+ NS_LOG_FUNCTION (this << GetCurrentPkt (deviceId)); |
+ NS_LOG_INFO ("UID is " << GetCurrentPkt (deviceId)->GetUid () << ")"); |
- NS_ASSERT (m_state == PROPAGATING); |
- m_state = IDLE; |
+ NS_ASSERT (GetState (deviceId) == PROPAGATING); |
+ SetState (deviceId, IDLE); |
} |
uint32_t |
@@ -304,9 +332,9 @@ |
} |
bool |
-CsmaChannel::IsBusy (void) |
+CsmaChannel::IsBusy (uint32_t deviceId) |
{ |
- if (m_state == IDLE) |
+ if (GetState (deviceId) == IDLE) |
{ |
return false; |
} |
@@ -329,9 +357,9 @@ |
} |
WireState |
-CsmaChannel::GetState (void) |
+CsmaChannel::GetState (uint32_t deviceId) |
{ |
- return m_state; |
+ return m_state[m_fullDuplex ? deviceId : 0]; |
} |
Ptr<NetDevice> |
@@ -340,6 +368,36 @@ |
return GetCsmaDevice (i); |
} |
+Ptr<Packet> |
+CsmaChannel::GetCurrentPkt (uint32_t deviceId) |
+{ |
+ return m_currentPkt[m_fullDuplex ? deviceId : 0]; |
+} |
+ |
+void |
+CsmaChannel::SetCurrentPkt (uint32_t deviceId, Ptr<Packet> pkt) |
+{ |
+ m_currentPkt[m_fullDuplex ? deviceId : 0] = pkt; |
+} |
+ |
+uint32_t |
+CsmaChannel::GetCurrentSrc (uint32_t deviceId) |
+{ |
+ return m_currentSrc[m_fullDuplex ? deviceId : 0]; |
+} |
+ |
+void |
+CsmaChannel::SetCurrentSrc (uint32_t deviceId, uint32_t transmitterId) |
+{ |
+ m_currentSrc[m_fullDuplex ? deviceId : 0] = transmitterId; |
+} |
+ |
+void |
+CsmaChannel::SetState (uint32_t deviceId, WireState state) |
+{ |
+ m_state[m_fullDuplex ? deviceId : 0] = state; |
+} |
+ |
CsmaDeviceRec::CsmaDeviceRec () |
{ |
active = false; |