Make some DHCP options and host discovery configurable
- Added broadcast option - Made host discovery from DHCP configurable - Some code cleanups Change-Id: I42191c2fd17ef309c73a5382730d708686b835cd
Showing
11 changed files
with
364 additions
and
308 deletions
... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.cordvtn.impl; | 16 | package org.onosproject.cordvtn.impl; |
17 | 17 | ||
18 | -import com.google.common.collect.Lists; | ||
19 | import com.google.common.collect.Sets; | 18 | import com.google.common.collect.Sets; |
20 | import org.apache.felix.scr.annotations.Activate; | 19 | import org.apache.felix.scr.annotations.Activate; |
21 | import org.apache.felix.scr.annotations.Component; | 20 | import org.apache.felix.scr.annotations.Component; |
... | @@ -34,6 +33,7 @@ import org.onosproject.cordvtn.api.Instance; | ... | @@ -34,6 +33,7 @@ import org.onosproject.cordvtn.api.Instance; |
34 | import org.onosproject.core.ApplicationId; | 33 | import org.onosproject.core.ApplicationId; |
35 | import org.onosproject.core.CoreService; | 34 | import org.onosproject.core.CoreService; |
36 | import org.onosproject.dhcp.DhcpService; | 35 | import org.onosproject.dhcp.DhcpService; |
36 | +import org.onosproject.dhcp.IpAssignment; | ||
37 | import org.onosproject.mastership.MastershipService; | 37 | import org.onosproject.mastership.MastershipService; |
38 | import org.onosproject.net.ConnectPoint; | 38 | import org.onosproject.net.ConnectPoint; |
39 | import org.onosproject.net.DefaultAnnotations; | 39 | import org.onosproject.net.DefaultAnnotations; |
... | @@ -70,7 +70,7 @@ import org.onosproject.xosclient.api.XosAccess; | ... | @@ -70,7 +70,7 @@ import org.onosproject.xosclient.api.XosAccess; |
70 | import org.onosproject.xosclient.api.XosClientService; | 70 | import org.onosproject.xosclient.api.XosClientService; |
71 | import org.slf4j.Logger; | 71 | import org.slf4j.Logger; |
72 | 72 | ||
73 | -import java.util.List; | 73 | +import java.util.Date; |
74 | import java.util.Map; | 74 | import java.util.Map; |
75 | import java.util.Objects; | 75 | import java.util.Objects; |
76 | import java.util.Set; | 76 | import java.util.Set; |
... | @@ -82,6 +82,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -82,6 +82,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
82 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | 82 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; |
83 | import static org.onlab.util.Tools.groupedThreads; | 83 | import static org.onlab.util.Tools.groupedThreads; |
84 | import static org.onosproject.cordvtn.api.Instance.*; | 84 | import static org.onosproject.cordvtn.api.Instance.*; |
85 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced; | ||
86 | +import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT; | ||
85 | import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE; | 87 | import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE; |
86 | import static org.slf4j.LoggerFactory.getLogger; | 88 | import static org.slf4j.LoggerFactory.getLogger; |
87 | 89 | ||
... | @@ -97,6 +99,7 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv | ... | @@ -97,6 +99,7 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv |
97 | private static final String XOS_ACCESS_ERROR = "XOS access is not configured"; | 99 | private static final String XOS_ACCESS_ERROR = "XOS access is not configured"; |
98 | private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured"; | 100 | private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured"; |
99 | private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8"); | 101 | private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8"); |
102 | + private static final int DHCP_INFINITE_LEASE = -1; | ||
100 | 103 | ||
101 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 104 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
102 | protected CoreService coreService; | 105 | protected CoreService coreService; |
... | @@ -273,7 +276,6 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv | ... | @@ -273,7 +276,6 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv |
273 | arpProxy.addGateway(service.serviceIp(), privateGatewayMac); | 276 | arpProxy.addGateway(service.serviceIp(), privateGatewayMac); |
274 | arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance)); | 277 | arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance)); |
275 | } | 278 | } |
276 | - | ||
277 | if (!instance.isNestedInstance()) { | 279 | if (!instance.isNestedInstance()) { |
278 | registerDhcpLease(instance, service); | 280 | registerDhcpLease(instance, service); |
279 | } | 281 | } |
... | @@ -295,17 +297,25 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv | ... | @@ -295,17 +297,25 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv |
295 | } | 297 | } |
296 | 298 | ||
297 | private void registerDhcpLease(Instance instance, VtnService service) { | 299 | private void registerDhcpLease(Instance instance, VtnService service) { |
298 | - List<Ip4Address> options = Lists.newArrayList(); | 300 | + Ip4Address broadcast = Ip4Address.makeMaskedAddress( |
299 | - options.add(Ip4Address.makeMaskPrefix(service.subnet().prefixLength())); | 301 | + instance.ipAddress(), |
300 | - options.add(service.serviceIp().getIp4Address()); | 302 | + service.subnet().prefixLength()); |
301 | - options.add(service.serviceIp().getIp4Address()); | 303 | + |
302 | - options.add(DEFAULT_DNS); | 304 | + IpAssignment.Builder ipBuilder = IpAssignment.builder() |
305 | + .ipAddress(instance.ipAddress()) | ||
306 | + .leasePeriod(DHCP_INFINITE_LEASE) | ||
307 | + .timestamp(new Date()) | ||
308 | + .subnetMask(Ip4Address.makeMaskPrefix(service.subnet().prefixLength())) | ||
309 | + .broadcast(broadcast) | ||
310 | + .domainServer(DEFAULT_DNS) | ||
311 | + .assignmentStatus(Option_RangeNotEnforced); | ||
312 | + | ||
313 | + if (service.networkType() != MANAGEMENT) { | ||
314 | + ipBuilder = ipBuilder.routerAddress(service.serviceIp().getIp4Address()); | ||
315 | + } | ||
303 | 316 | ||
304 | log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress()); | 317 | log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress()); |
305 | - dhcpService.setStaticMapping(instance.mac(), | 318 | + dhcpService.setStaticMapping(instance.mac(), ipBuilder.build()); |
306 | - instance.ipAddress(), | ||
307 | - true, | ||
308 | - options); | ||
309 | } | 319 | } |
310 | 320 | ||
311 | private VtnService getVtnService(VtnServiceId serviceId) { | 321 | private VtnService getVtnService(VtnServiceId serviceId) { | ... | ... |
... | @@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; | ... | @@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; |
19 | import org.onlab.packet.MacAddress; | 19 | import org.onlab.packet.MacAddress; |
20 | import org.onosproject.net.HostId; | 20 | import org.onosproject.net.HostId; |
21 | 21 | ||
22 | -import java.util.List; | ||
23 | import java.util.Map; | 22 | import java.util.Map; |
24 | 23 | ||
25 | 24 | ||
... | @@ -58,16 +57,12 @@ public interface DhcpService { | ... | @@ -58,16 +57,12 @@ public interface DhcpService { |
58 | 57 | ||
59 | /** | 58 | /** |
60 | * Registers a static IP mapping with the DHCP Server. | 59 | * Registers a static IP mapping with the DHCP Server. |
61 | - * Supports rangeNotEnforced option | ||
62 | * | 60 | * |
63 | - * @param macID macID of the client | 61 | + * @param macAddress mac address to have a given ip assignment |
64 | - * @param ipAddress IP Address requested for the client | 62 | + * @param ipRequest ip address and dhcp options |
65 | - * @param rangeNotEnforced true if rangeNotEnforced was set and the mapping will be eternal | ||
66 | - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses if rangeNotEnforced was set | ||
67 | * @return true if the mapping was successfully added, false otherwise | 63 | * @return true if the mapping was successfully added, false otherwise |
68 | */ | 64 | */ |
69 | - boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress, boolean rangeNotEnforced, | 65 | + boolean setStaticMapping(MacAddress macAddress, IpAssignment ipRequest); |
70 | - List<Ip4Address> addressList); | ||
71 | 66 | ||
72 | /** | 67 | /** |
73 | * Removes a static IP mapping with the DHCP Server. | 68 | * Removes a static IP mapping with the DHCP Server. | ... | ... |
... | @@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; | ... | @@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; |
19 | import org.onlab.packet.MacAddress; | 19 | import org.onlab.packet.MacAddress; |
20 | import org.onosproject.net.HostId; | 20 | import org.onosproject.net.HostId; |
21 | 21 | ||
22 | -import java.util.List; | ||
23 | import java.util.Map; | 22 | import java.util.Map; |
24 | 23 | ||
25 | 24 | ||
... | @@ -41,7 +40,7 @@ public interface DhcpStore { | ... | @@ -41,7 +40,7 @@ public interface DhcpStore { |
41 | * | 40 | * |
42 | * @param hostId Host ID of the client requesting an IP | 41 | * @param hostId Host ID of the client requesting an IP |
43 | * @param requestedIP requested IP address | 42 | * @param requestedIP requested IP address |
44 | - * @return IP address assigned to the Mac ID | 43 | + * @return IP address assigned to the Mac address; null if no available IP |
45 | */ | 44 | */ |
46 | Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP); | 45 | Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP); |
47 | 46 | ||
... | @@ -50,14 +49,10 @@ public interface DhcpStore { | ... | @@ -50,14 +49,10 @@ public interface DhcpStore { |
50 | * Assigns the requested IP to the Mac ID, in response to a DHCP REQUEST message. | 49 | * Assigns the requested IP to the Mac ID, in response to a DHCP REQUEST message. |
51 | * | 50 | * |
52 | * @param hostId Host Id of the client requesting an IP | 51 | * @param hostId Host Id of the client requesting an IP |
53 | - * @param ipAddr IP Address being requested | 52 | + * @param ipAssignment ip assignment |
54 | - * @param leaseTime Lease time offered by the server for this mapping | ||
55 | - * @param rangeNotEnforced true if rangeNotEnforced was set | ||
56 | - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses if rangeNotEnforced was set | ||
57 | * @return returns true if the assignment was successful, false otherwise | 53 | * @return returns true if the assignment was successful, false otherwise |
58 | */ | 54 | */ |
59 | - boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced, | 55 | + boolean assignIP(HostId hostId, IpAssignment ipAssignment); |
60 | - List<Ip4Address> addressList); | ||
61 | 56 | ||
62 | 57 | ||
63 | /** | 58 | /** |
... | @@ -92,21 +87,19 @@ public interface DhcpStore { | ... | @@ -92,21 +87,19 @@ public interface DhcpStore { |
92 | /** | 87 | /** |
93 | * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time. | 88 | * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time. |
94 | * | 89 | * |
95 | - * @param macID macID of the client | 90 | + * @param macAddress mac address of the client |
96 | - * @param ipAddr IP Address requested for the client | 91 | + * @param ipAssignment ip address and dhcp options requested for the client |
97 | - * @param rangeNotEnforced true if rangeNotEnforced was set | ||
98 | - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses rangeNotEnforced was set | ||
99 | * @return true if the mapping was successfully registered, false otherwise | 92 | * @return true if the mapping was successfully registered, false otherwise |
100 | */ | 93 | */ |
101 | - boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean rangeNotEnforced, List<Ip4Address> addressList); | 94 | + boolean assignStaticIP(MacAddress macAddress, IpAssignment ipAssignment); |
102 | 95 | ||
103 | /** | 96 | /** |
104 | * Removes a static IP mapping associated with the given MAC ID from the DHCP Server. | 97 | * Removes a static IP mapping associated with the given MAC ID from the DHCP Server. |
105 | * | 98 | * |
106 | - * @param macID macID of the client | 99 | + * @param macAddress mac address of the client |
107 | * @return true if the mapping was successfully registered, false otherwise | 100 | * @return true if the mapping was successfully registered, false otherwise |
108 | */ | 101 | */ |
109 | - boolean removeStaticIP(MacAddress macID); | 102 | + boolean removeStaticIP(MacAddress macAddress); |
110 | 103 | ||
111 | /** | 104 | /** |
112 | * Returns the list of all the available IPs with the server. | 105 | * Returns the list of all the available IPs with the server. | ... | ... |
... | @@ -27,22 +27,15 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -27,22 +27,15 @@ import static com.google.common.base.Preconditions.checkNotNull; |
27 | */ | 27 | */ |
28 | public final class IpAssignment { | 28 | public final class IpAssignment { |
29 | 29 | ||
30 | + // TODO make some dhcp options optional | ||
30 | private final Ip4Address ipAddress; | 31 | private final Ip4Address ipAddress; |
31 | - | ||
32 | private final Date timestamp; | 32 | private final Date timestamp; |
33 | - | ||
34 | private final long leasePeriod; | 33 | private final long leasePeriod; |
35 | - | ||
36 | private final Ip4Address subnetMask; | 34 | private final Ip4Address subnetMask; |
37 | - | 35 | + private final Ip4Address broadcast; |
38 | private final Ip4Address dhcpServer; | 36 | private final Ip4Address dhcpServer; |
39 | - | ||
40 | private final Ip4Address routerAddress; | 37 | private final Ip4Address routerAddress; |
41 | - | ||
42 | private final Ip4Address domainServer; | 38 | private final Ip4Address domainServer; |
43 | - | ||
44 | - private final boolean rangeNotEnforced; | ||
45 | - | ||
46 | private final AssignmentStatus assignmentStatus; | 39 | private final AssignmentStatus assignmentStatus; |
47 | 40 | ||
48 | public enum AssignmentStatus { | 41 | public enum AssignmentStatus { |
... | @@ -52,8 +45,10 @@ public final class IpAssignment { | ... | @@ -52,8 +45,10 @@ public final class IpAssignment { |
52 | Option_Requested, | 45 | Option_Requested, |
53 | 46 | ||
54 | /** | 47 | /** |
55 | - * IP Assignment has been requested by a OpenStack. | 48 | + * Static IP Assignment with unregistered IP range. |
49 | + * This assignment can only be added or removed by set or remove static mapping. | ||
56 | */ | 50 | */ |
51 | + // TODO allow multiple IP ranges and remove this option | ||
57 | Option_RangeNotEnforced, | 52 | Option_RangeNotEnforced, |
58 | /** | 53 | /** |
59 | * IP has been assigned to a host. | 54 | * IP has been assigned to a host. |
... | @@ -70,30 +65,34 @@ public final class IpAssignment { | ... | @@ -70,30 +65,34 @@ public final class IpAssignment { |
70 | * Constructor for IPAssignment, where the ipAddress, the lease period, the timestamp | 65 | * Constructor for IPAssignment, where the ipAddress, the lease period, the timestamp |
71 | * and assignment status is supplied. | 66 | * and assignment status is supplied. |
72 | * | 67 | * |
73 | - * @param ipAddress | 68 | + * @param ipAddress ip address to assign |
74 | - * @param leasePeriod | 69 | + * @param leasePeriod lease period |
75 | - * @param timestamp | 70 | + * @param timestamp time stamp of the assignment |
76 | - * @param assignmentStatus | 71 | + * @param assignmentStatus statue of the assignment |
77 | - * @param subnetMask | 72 | + * @param subnetMask subnet mask of assigned ip range |
78 | - * @param dhcpServer | 73 | + * @param broadcast broadcast address |
79 | - * @param routerAddress | 74 | + * @param dhcpServer dhcp server address |
80 | - * @param domainServer | 75 | + * @param routerAddress router address |
81 | - * @param rangeNotEnforced | 76 | + * @param domainServer domain server address |
82 | */ | 77 | */ |
83 | private IpAssignment(Ip4Address ipAddress, | 78 | private IpAssignment(Ip4Address ipAddress, |
84 | long leasePeriod, | 79 | long leasePeriod, |
85 | Date timestamp, | 80 | Date timestamp, |
86 | - AssignmentStatus assignmentStatus, Ip4Address subnetMask, Ip4Address dhcpServer, | 81 | + AssignmentStatus assignmentStatus, |
87 | - Ip4Address routerAddress, Ip4Address domainServer, boolean rangeNotEnforced) { | 82 | + Ip4Address subnetMask, |
83 | + Ip4Address broadcast, | ||
84 | + Ip4Address dhcpServer, | ||
85 | + Ip4Address routerAddress, | ||
86 | + Ip4Address domainServer) { | ||
88 | this.ipAddress = ipAddress; | 87 | this.ipAddress = ipAddress; |
89 | this.leasePeriod = leasePeriod; | 88 | this.leasePeriod = leasePeriod; |
90 | this.timestamp = timestamp; | 89 | this.timestamp = timestamp; |
91 | this.assignmentStatus = assignmentStatus; | 90 | this.assignmentStatus = assignmentStatus; |
92 | this.subnetMask = subnetMask; | 91 | this.subnetMask = subnetMask; |
92 | + this.broadcast = broadcast; | ||
93 | this.dhcpServer = dhcpServer; | 93 | this.dhcpServer = dhcpServer; |
94 | this.routerAddress = routerAddress; | 94 | this.routerAddress = routerAddress; |
95 | this.domainServer = domainServer; | 95 | this.domainServer = domainServer; |
96 | - this.rangeNotEnforced = rangeNotEnforced; | ||
97 | } | 96 | } |
98 | 97 | ||
99 | /** | 98 | /** |
... | @@ -141,26 +140,51 @@ public final class IpAssignment { | ... | @@ -141,26 +140,51 @@ public final class IpAssignment { |
141 | return (int) this.leasePeriod * 1000; | 140 | return (int) this.leasePeriod * 1000; |
142 | } | 141 | } |
143 | 142 | ||
143 | + /** | ||
144 | + * Returns subnet mask of the IP assignment. | ||
145 | + * | ||
146 | + * @return subnet mask | ||
147 | + */ | ||
144 | public Ip4Address subnetMask() { | 148 | public Ip4Address subnetMask() { |
145 | return subnetMask; | 149 | return subnetMask; |
146 | } | 150 | } |
147 | 151 | ||
152 | + /** | ||
153 | + * Returns broadcast address of the IP assignment. | ||
154 | + * | ||
155 | + * @return broadcast address | ||
156 | + */ | ||
157 | + public Ip4Address broadcast() { | ||
158 | + return broadcast; | ||
159 | + } | ||
160 | + | ||
161 | + /** | ||
162 | + * Returns dhcp server of the IP assignment. | ||
163 | + * | ||
164 | + * @return dhcp server ip address | ||
165 | + */ | ||
148 | public Ip4Address dhcpServer() { | 166 | public Ip4Address dhcpServer() { |
149 | return dhcpServer; | 167 | return dhcpServer; |
150 | } | 168 | } |
151 | 169 | ||
170 | + /** | ||
171 | + * Returns router address of the IP assignment. | ||
172 | + * | ||
173 | + * @return router ip address | ||
174 | + */ | ||
152 | public Ip4Address routerAddress() { | 175 | public Ip4Address routerAddress() { |
153 | return routerAddress; | 176 | return routerAddress; |
154 | } | 177 | } |
155 | 178 | ||
179 | + /** | ||
180 | + * Returns domain server address. | ||
181 | + * | ||
182 | + * @return domain server ip address | ||
183 | + */ | ||
156 | public Ip4Address domainServer() { | 184 | public Ip4Address domainServer() { |
157 | return domainServer; | 185 | return domainServer; |
158 | } | 186 | } |
159 | 187 | ||
160 | - public boolean rangeNotEnforced() { | ||
161 | - return rangeNotEnforced; | ||
162 | - } | ||
163 | - | ||
164 | @Override | 188 | @Override |
165 | public String toString() { | 189 | public String toString() { |
166 | return MoreObjects.toStringHelper(getClass()) | 190 | return MoreObjects.toStringHelper(getClass()) |
... | @@ -169,10 +193,10 @@ public final class IpAssignment { | ... | @@ -169,10 +193,10 @@ public final class IpAssignment { |
169 | .add("lease", leasePeriod) | 193 | .add("lease", leasePeriod) |
170 | .add("assignmentStatus", assignmentStatus) | 194 | .add("assignmentStatus", assignmentStatus) |
171 | .add("subnetMask", subnetMask) | 195 | .add("subnetMask", subnetMask) |
196 | + .add("broadcast", broadcast) | ||
172 | .add("dhcpServer", dhcpServer) | 197 | .add("dhcpServer", dhcpServer) |
173 | .add("routerAddress", routerAddress) | 198 | .add("routerAddress", routerAddress) |
174 | .add("domainServer", domainServer) | 199 | .add("domainServer", domainServer) |
175 | - .add("rangeNotEnforced", rangeNotEnforced) | ||
176 | .toString(); | 200 | .toString(); |
177 | } | 201 | } |
178 | 202 | ||
... | @@ -201,25 +225,16 @@ public final class IpAssignment { | ... | @@ -201,25 +225,16 @@ public final class IpAssignment { |
201 | public static final class Builder { | 225 | public static final class Builder { |
202 | 226 | ||
203 | private Ip4Address ipAddress; | 227 | private Ip4Address ipAddress; |
204 | - | ||
205 | private Date timeStamp; | 228 | private Date timeStamp; |
206 | - | ||
207 | private long leasePeriod; | 229 | private long leasePeriod; |
208 | - | ||
209 | private AssignmentStatus assignmentStatus; | 230 | private AssignmentStatus assignmentStatus; |
210 | - | ||
211 | private Ip4Address subnetMask; | 231 | private Ip4Address subnetMask; |
212 | - | 232 | + private Ip4Address broadcast; |
213 | private Ip4Address dhcpServer; | 233 | private Ip4Address dhcpServer; |
214 | - | ||
215 | - private Ip4Address domainServer; | ||
216 | - | ||
217 | private Ip4Address routerAddress; | 234 | private Ip4Address routerAddress; |
218 | - | 235 | + private Ip4Address domainServer; |
219 | - private boolean rangeNotEnforced = false; | ||
220 | 236 | ||
221 | private Builder() { | 237 | private Builder() { |
222 | - | ||
223 | } | 238 | } |
224 | 239 | ||
225 | private Builder(IpAssignment ipAssignment) { | 240 | private Builder(IpAssignment ipAssignment) { |
... | @@ -227,12 +242,24 @@ public final class IpAssignment { | ... | @@ -227,12 +242,24 @@ public final class IpAssignment { |
227 | timeStamp = ipAssignment.timestamp(); | 242 | timeStamp = ipAssignment.timestamp(); |
228 | leasePeriod = ipAssignment.leasePeriod(); | 243 | leasePeriod = ipAssignment.leasePeriod(); |
229 | assignmentStatus = ipAssignment.assignmentStatus(); | 244 | assignmentStatus = ipAssignment.assignmentStatus(); |
245 | + subnetMask = ipAssignment.subnetMask(); | ||
246 | + broadcast = ipAssignment.broadcast(); | ||
247 | + dhcpServer = ipAssignment.dhcpServer(); | ||
248 | + routerAddress = ipAssignment.routerAddress(); | ||
249 | + domainServer = ipAssignment.domainServer(); | ||
230 | } | 250 | } |
231 | 251 | ||
232 | public IpAssignment build() { | 252 | public IpAssignment build() { |
233 | validateInputs(); | 253 | validateInputs(); |
234 | - return new IpAssignment(ipAddress, leasePeriod, timeStamp, assignmentStatus, subnetMask, | 254 | + return new IpAssignment(ipAddress, |
235 | - dhcpServer, routerAddress, domainServer, rangeNotEnforced); | 255 | + leasePeriod, |
256 | + timeStamp, | ||
257 | + assignmentStatus, | ||
258 | + subnetMask, | ||
259 | + broadcast, | ||
260 | + dhcpServer, | ||
261 | + routerAddress, | ||
262 | + domainServer); | ||
236 | } | 263 | } |
237 | 264 | ||
238 | public Builder ipAddress(Ip4Address addr) { | 265 | public Builder ipAddress(Ip4Address addr) { |
... | @@ -260,6 +287,11 @@ public final class IpAssignment { | ... | @@ -260,6 +287,11 @@ public final class IpAssignment { |
260 | return this; | 287 | return this; |
261 | } | 288 | } |
262 | 289 | ||
290 | + public Builder broadcast(Ip4Address broadcast) { | ||
291 | + this.broadcast = broadcast; | ||
292 | + return this; | ||
293 | + } | ||
294 | + | ||
263 | public Builder dhcpServer(Ip4Address dhcpServer) { | 295 | public Builder dhcpServer(Ip4Address dhcpServer) { |
264 | this.dhcpServer = dhcpServer; | 296 | this.dhcpServer = dhcpServer; |
265 | return this; | 297 | return this; |
... | @@ -275,25 +307,12 @@ public final class IpAssignment { | ... | @@ -275,25 +307,12 @@ public final class IpAssignment { |
275 | return this; | 307 | return this; |
276 | } | 308 | } |
277 | 309 | ||
278 | - public Builder rangeNotEnforced(boolean rangeNotEnforced) { | ||
279 | - this.rangeNotEnforced = rangeNotEnforced; | ||
280 | - return this; | ||
281 | - } | ||
282 | - | ||
283 | - | ||
284 | private void validateInputs() { | 310 | private void validateInputs() { |
285 | checkNotNull(ipAddress, "IP Address must be specified"); | 311 | checkNotNull(ipAddress, "IP Address must be specified"); |
286 | checkNotNull(assignmentStatus, "Assignment Status must be specified"); | 312 | checkNotNull(assignmentStatus, "Assignment Status must be specified"); |
287 | checkNotNull(leasePeriod, "Lease Period must be specified"); | 313 | checkNotNull(leasePeriod, "Lease Period must be specified"); |
288 | checkNotNull(timeStamp, "Timestamp must be specified"); | 314 | checkNotNull(timeStamp, "Timestamp must be specified"); |
289 | 315 | ||
290 | - if (rangeNotEnforced) { | ||
291 | - checkNotNull(subnetMask, "subnetMask must be specified in case of rangeNotEnforced"); | ||
292 | - checkNotNull(dhcpServer, "dhcpServer must be specified in case of rangeNotEnforced"); | ||
293 | - checkNotNull(domainServer, "domainServer must be specified in case of rangeNotEnforced"); | ||
294 | - checkNotNull(routerAddress, "routerAddress must be specified in case of rangeNotEnforced"); | ||
295 | - } | ||
296 | - | ||
297 | switch (assignmentStatus) { | 316 | switch (assignmentStatus) { |
298 | case Option_Requested: | 317 | case Option_Requested: |
299 | case Option_RangeNotEnforced: | 318 | case Option_RangeNotEnforced: | ... | ... |
... | @@ -15,13 +15,17 @@ | ... | @@ -15,13 +15,17 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.dhcp.cli; | 16 | package org.onosproject.dhcp.cli; |
17 | 17 | ||
18 | -import com.google.common.collect.Lists; | ||
19 | import org.apache.karaf.shell.commands.Argument; | 18 | import org.apache.karaf.shell.commands.Argument; |
20 | import org.apache.karaf.shell.commands.Command; | 19 | import org.apache.karaf.shell.commands.Command; |
21 | import org.onlab.packet.Ip4Address; | 20 | import org.onlab.packet.Ip4Address; |
22 | import org.onlab.packet.MacAddress; | 21 | import org.onlab.packet.MacAddress; |
23 | import org.onosproject.cli.AbstractShellCommand; | 22 | import org.onosproject.cli.AbstractShellCommand; |
24 | import org.onosproject.dhcp.DhcpService; | 23 | import org.onosproject.dhcp.DhcpService; |
24 | +import org.onosproject.dhcp.IpAssignment; | ||
25 | + | ||
26 | +import java.util.Date; | ||
27 | + | ||
28 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested; | ||
25 | 29 | ||
26 | /** | 30 | /** |
27 | * Registers a static MAC Address to IP Mapping with the DHCP Server. | 31 | * Registers a static MAC Address to IP Mapping with the DHCP Server. |
... | @@ -49,7 +53,15 @@ public class DhcpSetStaticMapping extends AbstractShellCommand { | ... | @@ -49,7 +53,15 @@ public class DhcpSetStaticMapping extends AbstractShellCommand { |
49 | try { | 53 | try { |
50 | MacAddress macID = MacAddress.valueOf(macAddr); | 54 | MacAddress macID = MacAddress.valueOf(macAddr); |
51 | Ip4Address ipAddress = Ip4Address.valueOf(ipAddr); | 55 | Ip4Address ipAddress = Ip4Address.valueOf(ipAddr); |
52 | - if (dhcpService.setStaticMapping(macID, ipAddress, false, Lists.newArrayList())) { | 56 | + |
57 | + IpAssignment ipAssignment = IpAssignment.builder() | ||
58 | + .ipAddress(ipAddress) | ||
59 | + .leasePeriod(dhcpService.getLeaseTime()) | ||
60 | + .timestamp(new Date()) | ||
61 | + .assignmentStatus(Option_Requested) | ||
62 | + .build(); | ||
63 | + | ||
64 | + if (dhcpService.setStaticMapping(macID, ipAssignment)) { | ||
53 | print(DHCP_SUCCESS); | 65 | print(DHCP_SUCCESS); |
54 | } else { | 66 | } else { |
55 | print(DHCP_FAILURE); | 67 | print(DHCP_FAILURE); | ... | ... |
... | @@ -15,11 +15,13 @@ | ... | @@ -15,11 +15,13 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.dhcp.impl; | 16 | package org.onosproject.dhcp.impl; |
17 | 17 | ||
18 | +import com.google.common.base.Strings; | ||
18 | import com.google.common.collect.ImmutableSet; | 19 | import com.google.common.collect.ImmutableSet; |
19 | -import com.google.common.collect.Lists; | ||
20 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
21 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
22 | import org.apache.felix.scr.annotations.Deactivate; | 22 | import org.apache.felix.scr.annotations.Deactivate; |
23 | +import org.apache.felix.scr.annotations.Modified; | ||
24 | +import org.apache.felix.scr.annotations.Property; | ||
23 | import org.apache.felix.scr.annotations.Reference; | 25 | import org.apache.felix.scr.annotations.Reference; |
24 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 26 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
25 | import org.apache.felix.scr.annotations.Service; | 27 | import org.apache.felix.scr.annotations.Service; |
... | @@ -38,6 +40,8 @@ import org.onlab.packet.TpPort; | ... | @@ -38,6 +40,8 @@ import org.onlab.packet.TpPort; |
38 | import org.onlab.packet.UDP; | 40 | import org.onlab.packet.UDP; |
39 | import org.onlab.packet.VlanId; | 41 | import org.onlab.packet.VlanId; |
40 | import org.onlab.util.Timer; | 42 | import org.onlab.util.Timer; |
43 | +import org.onlab.util.Tools; | ||
44 | +import org.onosproject.cfg.ComponentConfigService; | ||
41 | import org.onosproject.core.ApplicationId; | 45 | import org.onosproject.core.ApplicationId; |
42 | import org.onosproject.core.CoreService; | 46 | import org.onosproject.core.CoreService; |
43 | import org.onosproject.dhcp.DhcpService; | 47 | import org.onosproject.dhcp.DhcpService; |
... | @@ -66,19 +70,31 @@ import org.onosproject.net.packet.PacketProcessor; | ... | @@ -66,19 +70,31 @@ import org.onosproject.net.packet.PacketProcessor; |
66 | import org.onosproject.net.packet.PacketService; | 70 | import org.onosproject.net.packet.PacketService; |
67 | import org.onosproject.net.provider.AbstractProvider; | 71 | import org.onosproject.net.provider.AbstractProvider; |
68 | import org.onosproject.net.provider.ProviderId; | 72 | import org.onosproject.net.provider.ProviderId; |
73 | +import org.osgi.service.component.ComponentContext; | ||
69 | import org.slf4j.Logger; | 74 | import org.slf4j.Logger; |
70 | import org.slf4j.LoggerFactory; | 75 | import org.slf4j.LoggerFactory; |
71 | 76 | ||
72 | import java.nio.ByteBuffer; | 77 | import java.nio.ByteBuffer; |
73 | import java.util.ArrayList; | 78 | import java.util.ArrayList; |
74 | import java.util.Date; | 79 | import java.util.Date; |
80 | +import java.util.Dictionary; | ||
75 | import java.util.HashSet; | 81 | import java.util.HashSet; |
76 | import java.util.List; | 82 | import java.util.List; |
77 | import java.util.Map; | 83 | import java.util.Map; |
78 | import java.util.Objects; | 84 | import java.util.Objects; |
85 | +import java.util.Optional; | ||
79 | import java.util.Set; | 86 | import java.util.Set; |
80 | import java.util.concurrent.TimeUnit; | 87 | import java.util.concurrent.TimeUnit; |
88 | + | ||
89 | +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_DHCPServerIp; | ||
90 | +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType; | ||
91 | +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_RequestedIP; | ||
92 | +import static org.onlab.packet.DHCPPacketType.DHCPACK; | ||
93 | +import static org.onlab.packet.DHCPPacketType.DHCPNAK; | ||
94 | +import static org.onlab.packet.DHCPPacketType.DHCPOFFER; | ||
81 | import static org.onlab.packet.MacAddress.valueOf; | 95 | import static org.onlab.packet.MacAddress.valueOf; |
96 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced; | ||
97 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested; | ||
82 | import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; | 98 | import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; |
83 | 99 | ||
84 | /** | 100 | /** |
... | @@ -89,6 +105,9 @@ import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FAC | ... | @@ -89,6 +105,9 @@ import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FAC |
89 | public class DhcpManager implements DhcpService { | 105 | public class DhcpManager implements DhcpService { |
90 | 106 | ||
91 | private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcp", true); | 107 | private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcp", true); |
108 | + private static final String ALLOW_HOST_DISCOVERY = "allowHostDiscovery"; | ||
109 | + private static final boolean DEFAULT_ALLOW_HOST_DISCOVERY = false; | ||
110 | + | ||
92 | private final Logger log = LoggerFactory.getLogger(getClass()); | 111 | private final Logger log = LoggerFactory.getLogger(getClass()); |
93 | 112 | ||
94 | private final InternalConfigListener cfgListener = new InternalConfigListener(); | 113 | private final InternalConfigListener cfgListener = new InternalConfigListener(); |
... | @@ -120,44 +139,36 @@ public class DhcpManager implements DhcpService { | ... | @@ -120,44 +139,36 @@ public class DhcpManager implements DhcpService { |
120 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 139 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
121 | protected HostProviderRegistry hostProviderRegistry; | 140 | protected HostProviderRegistry hostProviderRegistry; |
122 | 141 | ||
123 | - protected HostProviderService hostProviderService; | 142 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
143 | + protected ComponentConfigService componentConfigService; | ||
124 | 144 | ||
125 | - private final HostProvider hostProvider = new InternalHostProvider(); | 145 | + @Property(name = ALLOW_HOST_DISCOVERY, boolValue = DEFAULT_ALLOW_HOST_DISCOVERY, |
146 | + label = "Allow host discovery from DHCP request") | ||
147 | + private boolean allowHostDiscovery = DEFAULT_ALLOW_HOST_DISCOVERY; | ||
126 | 148 | ||
149 | + protected HostProviderService hostProviderService; | ||
150 | + private final HostProvider hostProvider = new InternalHostProvider(); | ||
127 | private ApplicationId appId; | 151 | private ApplicationId appId; |
128 | 152 | ||
129 | // Hardcoded values are default values. | 153 | // Hardcoded values are default values. |
130 | - | ||
131 | - private static Ip4Address myIP = Ip4Address.valueOf("10.0.0.2"); | ||
132 | - | ||
133 | - private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f"); | ||
134 | - | ||
135 | /** | 154 | /** |
136 | * leaseTime - 10 mins or 600s. | 155 | * leaseTime - 10 mins or 600s. |
137 | * renewalTime - 5 mins or 300s. | 156 | * renewalTime - 5 mins or 300s. |
138 | * rebindingTime - 6 mins or 360s. | 157 | * rebindingTime - 6 mins or 360s. |
139 | */ | 158 | */ |
140 | - | ||
141 | private static int leaseTime = 600; | 159 | private static int leaseTime = 600; |
142 | - | ||
143 | private static int renewalTime = 300; | 160 | private static int renewalTime = 300; |
144 | - | ||
145 | private static int rebindingTime = 360; | 161 | private static int rebindingTime = 360; |
146 | - | ||
147 | private static byte packetTTL = (byte) 127; | 162 | private static byte packetTTL = (byte) 127; |
148 | - | ||
149 | private static Ip4Address subnetMask = Ip4Address.valueOf("255.0.0.0"); | 163 | private static Ip4Address subnetMask = Ip4Address.valueOf("255.0.0.0"); |
150 | - | ||
151 | private static Ip4Address broadcastAddress = Ip4Address.valueOf("10.255.255.255"); | 164 | private static Ip4Address broadcastAddress = Ip4Address.valueOf("10.255.255.255"); |
152 | - | ||
153 | private static Ip4Address routerAddress = Ip4Address.valueOf("10.0.0.2"); | 165 | private static Ip4Address routerAddress = Ip4Address.valueOf("10.0.0.2"); |
154 | - | ||
155 | private static Ip4Address domainServer = Ip4Address.valueOf("10.0.0.2"); | 166 | private static Ip4Address domainServer = Ip4Address.valueOf("10.0.0.2"); |
156 | - | 167 | + private static Ip4Address myIP = Ip4Address.valueOf("10.0.0.2"); |
168 | + private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f"); | ||
157 | private static final Ip4Address IP_BROADCAST = Ip4Address.valueOf("255.255.255.255"); | 169 | private static final Ip4Address IP_BROADCAST = Ip4Address.valueOf("255.255.255.255"); |
158 | 170 | ||
159 | protected Timeout timeout; | 171 | protected Timeout timeout; |
160 | - | ||
161 | protected static int timerDelay = 2; | 172 | protected static int timerDelay = 2; |
162 | 173 | ||
163 | @Activate | 174 | @Activate |
... | @@ -165,6 +176,7 @@ public class DhcpManager implements DhcpService { | ... | @@ -165,6 +176,7 @@ public class DhcpManager implements DhcpService { |
165 | // start the dhcp server | 176 | // start the dhcp server |
166 | appId = coreService.registerApplication("org.onosproject.dhcp"); | 177 | appId = coreService.registerApplication("org.onosproject.dhcp"); |
167 | 178 | ||
179 | + componentConfigService.registerProperties(getClass()); | ||
168 | cfgService.addListener(cfgListener); | 180 | cfgService.addListener(cfgListener); |
169 | factories.forEach(cfgService::registerConfigFactory); | 181 | factories.forEach(cfgService::registerConfigFactory); |
170 | cfgListener.reconfigureNetwork(cfgService.getConfig(appId, DhcpConfig.class)); | 182 | cfgListener.reconfigureNetwork(cfgService.getConfig(appId, DhcpConfig.class)); |
... | @@ -187,6 +199,19 @@ public class DhcpManager implements DhcpService { | ... | @@ -187,6 +199,19 @@ public class DhcpManager implements DhcpService { |
187 | log.info("Stopped"); | 199 | log.info("Stopped"); |
188 | } | 200 | } |
189 | 201 | ||
202 | + @Modified | ||
203 | + protected void modified(ComponentContext context) { | ||
204 | + Dictionary<?, ?> properties = context.getProperties(); | ||
205 | + | ||
206 | + String updatedConfig = Tools.get(properties, ALLOW_HOST_DISCOVERY); | ||
207 | + if (!Strings.isNullOrEmpty(updatedConfig)) { | ||
208 | + allowHostDiscovery = Boolean.valueOf(updatedConfig); | ||
209 | + log.info("Host discovery is set to {}", updatedConfig); | ||
210 | + } | ||
211 | + | ||
212 | + log.info("Modified"); | ||
213 | + } | ||
214 | + | ||
190 | /** | 215 | /** |
191 | * Request packet in via PacketService. | 216 | * Request packet in via PacketService. |
192 | */ | 217 | */ |
... | @@ -241,12 +266,10 @@ public class DhcpManager implements DhcpService { | ... | @@ -241,12 +266,10 @@ public class DhcpManager implements DhcpService { |
241 | } | 266 | } |
242 | 267 | ||
243 | @Override | 268 | @Override |
244 | - public boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress, boolean rangeNotEnforced, | 269 | + public boolean setStaticMapping(MacAddress macAddress, IpAssignment ipAssignment) { |
245 | - List<Ip4Address> addressList) { | 270 | + log.debug("setStaticMapping is called with Mac: {} IpAssignment: {}", |
246 | - log.debug("setStaticMapping is called with Mac: {}, Ip: {} addressList: {}", | 271 | + macAddress, ipAssignment); |
247 | - macID.toString(), ipAddress.toString(), addressList.toString()); | 272 | + return dhcpStore.assignStaticIP(macAddress, ipAssignment); |
248 | - | ||
249 | - return dhcpStore.assignStaticIP(macID, ipAddress, rangeNotEnforced, addressList); | ||
250 | } | 273 | } |
251 | 274 | ||
252 | @Override | 275 | @Override |
... | @@ -271,24 +294,25 @@ public class DhcpManager implements DhcpService { | ... | @@ -271,24 +294,25 @@ public class DhcpManager implements DhcpService { |
271 | */ | 294 | */ |
272 | private Ethernet buildReply(Ethernet packet, Ip4Address ipOffered, byte outgoingMessageType) { | 295 | private Ethernet buildReply(Ethernet packet, Ip4Address ipOffered, byte outgoingMessageType) { |
273 | 296 | ||
274 | - Ip4Address subnetMaskReply; | 297 | + // mandatory options |
275 | - Ip4Address dhcpServerReply; | 298 | + // TODO save and get the information below to/from IP assignment |
276 | - Ip4Address routerAddressReply; | 299 | + Ip4Address dhcpServerReply = myIP; |
277 | - Ip4Address domainServerReply; | 300 | + Ip4Address subnetMaskReply = subnetMask; |
278 | - IpAssignment ipAssignment; | 301 | + Ip4Address broadcastReply = broadcastAddress; |
302 | + | ||
303 | + // optional options | ||
304 | + Optional<Ip4Address> routerAddressReply = Optional.of(routerAddress); | ||
305 | + Optional<Ip4Address> domainServerReply = Optional.of(domainServer); | ||
279 | 306 | ||
280 | - ipAssignment = dhcpStore.getIpAssignmentFromAllocationMap(HostId.hostId(packet.getSourceMAC())); | 307 | + IpAssignment ipAssignment = dhcpStore.getIpAssignmentFromAllocationMap( |
308 | + HostId.hostId(packet.getSourceMAC())); | ||
281 | 309 | ||
282 | - if (ipAssignment != null && ipAssignment.rangeNotEnforced()) { | 310 | + if (ipAssignment != null && |
311 | + ipAssignment.assignmentStatus().equals(Option_RangeNotEnforced)) { | ||
283 | subnetMaskReply = ipAssignment.subnetMask(); | 312 | subnetMaskReply = ipAssignment.subnetMask(); |
284 | - dhcpServerReply = ipAssignment.dhcpServer(); | 313 | + broadcastReply = ipAssignment.broadcast(); |
285 | - domainServerReply = ipAssignment.domainServer(); | 314 | + routerAddressReply = Optional.ofNullable(ipAssignment.routerAddress()); |
286 | - routerAddressReply = ipAssignment.routerAddress(); | 315 | + domainServerReply = Optional.ofNullable(ipAssignment.domainServer()); |
287 | - } else { | ||
288 | - subnetMaskReply = subnetMask; | ||
289 | - dhcpServerReply = myIP; | ||
290 | - routerAddressReply = routerAddress; | ||
291 | - domainServerReply = domainServer; | ||
292 | } | 316 | } |
293 | 317 | ||
294 | // Ethernet Frame. | 318 | // Ethernet Frame. |
... | @@ -335,7 +359,7 @@ public class DhcpManager implements DhcpService { | ... | @@ -335,7 +359,7 @@ public class DhcpManager implements DhcpService { |
335 | List<DHCPOption> optionList = new ArrayList<>(); | 359 | List<DHCPOption> optionList = new ArrayList<>(); |
336 | 360 | ||
337 | // DHCP Message Type. | 361 | // DHCP Message Type. |
338 | - option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()); | 362 | + option.setCode(OptionCode_MessageType.getValue()); |
339 | option.setLength((byte) 1); | 363 | option.setLength((byte) 1); |
340 | byte[] optionData = {outgoingMessageType}; | 364 | byte[] optionData = {outgoingMessageType}; |
341 | option.setData(optionData); | 365 | option.setData(optionData); |
... | @@ -343,13 +367,12 @@ public class DhcpManager implements DhcpService { | ... | @@ -343,13 +367,12 @@ public class DhcpManager implements DhcpService { |
343 | 367 | ||
344 | // DHCP Server Identifier. | 368 | // DHCP Server Identifier. |
345 | option = new DHCPOption(); | 369 | option = new DHCPOption(); |
346 | - option.setCode(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()); | 370 | + option.setCode(OptionCode_DHCPServerIp.getValue()); |
347 | option.setLength((byte) 4); | 371 | option.setLength((byte) 4); |
348 | option.setData(dhcpServerReply.toOctets()); | 372 | option.setData(dhcpServerReply.toOctets()); |
349 | optionList.add(option); | 373 | optionList.add(option); |
350 | 374 | ||
351 | if (outgoingMessageType != DHCPPacketType.DHCPNAK.getValue()) { | 375 | if (outgoingMessageType != DHCPPacketType.DHCPNAK.getValue()) { |
352 | - | ||
353 | // IP Address Lease Time. | 376 | // IP Address Lease Time. |
354 | option = new DHCPOption(); | 377 | option = new DHCPOption(); |
355 | option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue()); | 378 | option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue()); |
... | @@ -383,23 +406,27 @@ public class DhcpManager implements DhcpService { | ... | @@ -383,23 +406,27 @@ public class DhcpManager implements DhcpService { |
383 | option = new DHCPOption(); | 406 | option = new DHCPOption(); |
384 | option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue()); | 407 | option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue()); |
385 | option.setLength((byte) 4); | 408 | option.setLength((byte) 4); |
386 | - option.setData(broadcastAddress.toOctets()); | 409 | + option.setData(broadcastReply.toOctets()); |
387 | optionList.add(option); | 410 | optionList.add(option); |
388 | 411 | ||
389 | // Router Address. | 412 | // Router Address. |
413 | + if (routerAddressReply.isPresent()) { | ||
390 | option = new DHCPOption(); | 414 | option = new DHCPOption(); |
391 | option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue()); | 415 | option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue()); |
392 | option.setLength((byte) 4); | 416 | option.setLength((byte) 4); |
393 | - option.setData(routerAddressReply.toOctets()); | 417 | + option.setData(routerAddressReply.get().toOctets()); |
394 | optionList.add(option); | 418 | optionList.add(option); |
419 | + } | ||
395 | 420 | ||
396 | // DNS Server Address. | 421 | // DNS Server Address. |
422 | + if (domainServerReply.isPresent()) { | ||
397 | option = new DHCPOption(); | 423 | option = new DHCPOption(); |
398 | option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue()); | 424 | option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue()); |
399 | option.setLength((byte) 4); | 425 | option.setLength((byte) 4); |
400 | - option.setData(domainServerReply.toOctets()); | 426 | + option.setData(domainServerReply.get().toOctets()); |
401 | optionList.add(option); | 427 | optionList.add(option); |
402 | } | 428 | } |
429 | + } | ||
403 | 430 | ||
404 | // End Option. | 431 | // End Option. |
405 | option = new DHCPOption(); | 432 | option = new DHCPOption(); |
... | @@ -439,104 +466,94 @@ public class DhcpManager implements DhcpService { | ... | @@ -439,104 +466,94 @@ public class DhcpManager implements DhcpService { |
439 | * @param dhcpPayload the extracted DHCP payload | 466 | * @param dhcpPayload the extracted DHCP payload |
440 | */ | 467 | */ |
441 | private void processDhcpPacket(PacketContext context, DHCP dhcpPayload) { | 468 | private void processDhcpPacket(PacketContext context, DHCP dhcpPayload) { |
469 | + if (dhcpPayload == null) { | ||
470 | + log.debug("DHCP packet without payload, do nothing"); | ||
471 | + return; | ||
472 | + } | ||
473 | + | ||
442 | Ethernet packet = context.inPacket().parsed(); | 474 | Ethernet packet = context.inPacket().parsed(); |
475 | + DHCPPacketType incomingPacketType = null; | ||
443 | boolean flagIfRequestedIP = false; | 476 | boolean flagIfRequestedIP = false; |
444 | boolean flagIfServerIP = false; | 477 | boolean flagIfServerIP = false; |
445 | Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0"); | 478 | Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0"); |
446 | Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0"); | 479 | Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0"); |
447 | 480 | ||
448 | - if (dhcpPayload != null) { | ||
449 | - | ||
450 | - DHCPPacketType incomingPacketType = DHCPPacketType.getType(0); | ||
451 | for (DHCPOption option : dhcpPayload.getOptions()) { | 481 | for (DHCPOption option : dhcpPayload.getOptions()) { |
452 | - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()) { | 482 | + if (option.getCode() == OptionCode_MessageType.getValue()) { |
453 | byte[] data = option.getData(); | 483 | byte[] data = option.getData(); |
454 | incomingPacketType = DHCPPacketType.getType(data[0]); | 484 | incomingPacketType = DHCPPacketType.getType(data[0]); |
455 | } | 485 | } |
456 | - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue()) { | 486 | + if (option.getCode() == OptionCode_RequestedIP.getValue()) { |
457 | byte[] data = option.getData(); | 487 | byte[] data = option.getData(); |
458 | requestedIP = Ip4Address.valueOf(data); | 488 | requestedIP = Ip4Address.valueOf(data); |
459 | flagIfRequestedIP = true; | 489 | flagIfRequestedIP = true; |
460 | } | 490 | } |
461 | - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()) { | 491 | + if (option.getCode() == OptionCode_DHCPServerIp.getValue()) { |
462 | byte[] data = option.getData(); | 492 | byte[] data = option.getData(); |
463 | serverIP = Ip4Address.valueOf(data); | 493 | serverIP = Ip4Address.valueOf(data); |
464 | flagIfServerIP = true; | 494 | flagIfServerIP = true; |
465 | } | 495 | } |
466 | } | 496 | } |
497 | + | ||
498 | + if (incomingPacketType == null) { | ||
499 | + log.debug("No incoming packet type specified, ignore it"); | ||
500 | + return; | ||
501 | + } | ||
502 | + | ||
467 | DHCPPacketType outgoingPacketType; | 503 | DHCPPacketType outgoingPacketType; |
468 | MacAddress clientMac = new MacAddress(dhcpPayload.getClientHardwareAddress()); | 504 | MacAddress clientMac = new MacAddress(dhcpPayload.getClientHardwareAddress()); |
469 | VlanId vlanId = VlanId.vlanId(packet.getVlanID()); | 505 | VlanId vlanId = VlanId.vlanId(packet.getVlanID()); |
470 | HostId hostId = HostId.hostId(clientMac, vlanId); | 506 | HostId hostId = HostId.hostId(clientMac, vlanId); |
471 | 507 | ||
472 | - if (incomingPacketType.getValue() == DHCPPacketType.DHCPDISCOVER.getValue()) { | 508 | + switch (incomingPacketType) { |
473 | - | 509 | + case DHCPDISCOVER: |
474 | - outgoingPacketType = DHCPPacketType.DHCPOFFER; | 510 | + log.trace("DHCP DISCOVER received from {}", hostId); |
475 | - Ip4Address ipOffered = null; | 511 | + Ip4Address ipOffered = dhcpStore.suggestIP(hostId, requestedIP); |
476 | - ipOffered = dhcpStore.suggestIP(hostId, requestedIP); | ||
477 | - | ||
478 | if (ipOffered != null) { | 512 | if (ipOffered != null) { |
479 | - Ethernet ethReply = buildReply(packet, ipOffered, | 513 | + Ethernet ethReply = buildReply( |
480 | - (byte) outgoingPacketType.getValue()); | 514 | + packet, |
515 | + ipOffered, | ||
516 | + (byte) DHCPOFFER.getValue()); | ||
481 | sendReply(context, ethReply); | 517 | sendReply(context, ethReply); |
482 | } | 518 | } |
483 | - } else if (incomingPacketType.getValue() == DHCPPacketType.DHCPREQUEST.getValue()) { | 519 | + break; |
520 | + case DHCPREQUEST: | ||
521 | + log.trace("DHCP REQUEST received from {}", hostId); | ||
522 | + if (flagIfServerIP && !myIP.equals(serverIP)) { | ||
523 | + return; | ||
524 | + } | ||
484 | 525 | ||
485 | - if (flagIfServerIP && flagIfRequestedIP) { | 526 | + if (!flagIfRequestedIP) { |
486 | - // SELECTING state | 527 | + // this is renew or rebinding request |
528 | + int clientIp = dhcpPayload.getClientIPAddress(); | ||
529 | + requestedIP = Ip4Address.valueOf(clientIp); | ||
530 | + } | ||
487 | 531 | ||
532 | + IpAssignment ipAssignment = IpAssignment.builder() | ||
533 | + .ipAddress(requestedIP) | ||
534 | + .leasePeriod(leaseTime) | ||
535 | + .timestamp(new Date()) | ||
536 | + .assignmentStatus(Option_Requested).build(); | ||
488 | 537 | ||
489 | - if (dhcpStore.getIpAssignmentFromAllocationMap(HostId.hostId(clientMac)) | 538 | + if (dhcpStore.assignIP(hostId, ipAssignment)) { |
490 | - .rangeNotEnforced()) { | 539 | + outgoingPacketType = DHCPACK; |
491 | - outgoingPacketType = DHCPPacketType.DHCPACK; | ||
492 | - Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue()); | ||
493 | - sendReply(context, ethReply); | ||
494 | - } else { | ||
495 | - if (myIP.equals(serverIP)) { | ||
496 | - if (dhcpStore.assignIP(hostId, requestedIP, leaseTime, false, Lists.newArrayList())) { | ||
497 | - outgoingPacketType = DHCPPacketType.DHCPACK; | ||
498 | discoverHost(context, requestedIP); | 540 | discoverHost(context, requestedIP); |
499 | } else { | 541 | } else { |
500 | - outgoingPacketType = DHCPPacketType.DHCPNAK; | 542 | + outgoingPacketType = DHCPNAK; |
501 | - } | ||
502 | - Ethernet ethReply = buildReply(packet, requestedIP, | ||
503 | - (byte) outgoingPacketType.getValue()); | ||
504 | - sendReply(context, ethReply); | ||
505 | - } | ||
506 | - } | ||
507 | - } else if (flagIfRequestedIP) { | ||
508 | - // INIT-REBOOT state | ||
509 | - if (dhcpStore.assignIP(hostId, requestedIP, leaseTime, false, Lists.newArrayList())) { | ||
510 | - outgoingPacketType = DHCPPacketType.DHCPACK; | ||
511 | - Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue()); | ||
512 | - sendReply(context, ethReply); | ||
513 | - discoverHost(context, requestedIP); | ||
514 | } | 543 | } |
515 | 544 | ||
516 | - } else { | 545 | + Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue()); |
517 | - // RENEWING and REBINDING state | ||
518 | - int ciaadr = dhcpPayload.getClientIPAddress(); | ||
519 | - if (ciaadr != 0) { | ||
520 | - Ip4Address clientIaddr = Ip4Address.valueOf(ciaadr); | ||
521 | - if (dhcpStore.assignIP(hostId, clientIaddr, leaseTime, false, Lists.newArrayList())) { | ||
522 | - outgoingPacketType = DHCPPacketType.DHCPACK; | ||
523 | - discoverHost(context, clientIaddr); | ||
524 | - } else if (packet.getEtherType() == Ethernet.TYPE_IPV4 && | ||
525 | - ((IPv4) packet.getPayload()).getDestinationAddress() == myIP.toInt()) { | ||
526 | - outgoingPacketType = DHCPPacketType.DHCPNAK; | ||
527 | - } else { | ||
528 | - return; | ||
529 | - } | ||
530 | - Ethernet ethReply = buildReply(packet, clientIaddr, (byte) outgoingPacketType.getValue()); | ||
531 | sendReply(context, ethReply); | 546 | sendReply(context, ethReply); |
547 | + break; | ||
548 | + case DHCPRELEASE: | ||
549 | + log.trace("DHCP RELEASE received from {}", hostId); | ||
550 | + Ip4Address releaseIp = dhcpStore.releaseIP(hostId); | ||
551 | + if (releaseIp != null) { | ||
552 | + hostProviderService.removeIpFromHost(hostId, releaseIp); | ||
532 | } | 553 | } |
533 | - } | 554 | + break; |
534 | - } else if (incomingPacketType.getValue() == DHCPPacketType.DHCPRELEASE.getValue()) { | 555 | + default: |
535 | - Ip4Address ip4Address = dhcpStore.releaseIP(hostId); | 556 | + break; |
536 | - if (ip4Address != null) { | ||
537 | - hostProviderService.removeIpFromHost(hostId, ip4Address); | ||
538 | - } | ||
539 | - } | ||
540 | } | 557 | } |
541 | } | 558 | } |
542 | 559 | ||
... | @@ -575,6 +592,11 @@ public class DhcpManager implements DhcpService { | ... | @@ -575,6 +592,11 @@ public class DhcpManager implements DhcpService { |
575 | * @param ipAssigned IP Address assigned to the host by DHCP Manager | 592 | * @param ipAssigned IP Address assigned to the host by DHCP Manager |
576 | */ | 593 | */ |
577 | private void discoverHost(PacketContext context, Ip4Address ipAssigned) { | 594 | private void discoverHost(PacketContext context, Ip4Address ipAssigned) { |
595 | + if (!allowHostDiscovery) { | ||
596 | + // host discovery is not allowed, do nothing | ||
597 | + return; | ||
598 | + } | ||
599 | + | ||
578 | Ethernet packet = context.inPacket().parsed(); | 600 | Ethernet packet = context.inPacket().parsed(); |
579 | MacAddress mac = packet.getSourceMAC(); | 601 | MacAddress mac = packet.getSourceMAC(); |
580 | VlanId vlanId = VlanId.vlanId(packet.getVlanID()); | 602 | VlanId vlanId = VlanId.vlanId(packet.getVlanID()); |
... | @@ -585,6 +607,8 @@ public class DhcpManager implements DhcpService { | ... | @@ -585,6 +607,8 @@ public class DhcpManager implements DhcpService { |
585 | 607 | ||
586 | HostId hostId = HostId.hostId(mac, vlanId); | 608 | HostId hostId = HostId.hostId(mac, vlanId); |
587 | DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips); | 609 | DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips); |
610 | + | ||
611 | + log.info("Discovered host {}", desc); | ||
588 | hostProviderService.hostDetected(hostId, desc, false); | 612 | hostProviderService.hostDetected(hostId, desc, false); |
589 | } | 613 | } |
590 | 614 | ... | ... |
... | @@ -39,9 +39,10 @@ import org.slf4j.LoggerFactory; | ... | @@ -39,9 +39,10 @@ import org.slf4j.LoggerFactory; |
39 | 39 | ||
40 | import java.util.Date; | 40 | import java.util.Date; |
41 | import java.util.Map; | 41 | import java.util.Map; |
42 | -import java.util.List; | ||
43 | import java.util.HashMap; | 42 | import java.util.HashMap; |
44 | -import java.util.Objects; | 43 | + |
44 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Assigned; | ||
45 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced; | ||
45 | 46 | ||
46 | /** | 47 | /** |
47 | * Manages the pool of available IP Addresses in the network and | 48 | * Manages the pool of available IP Addresses in the network and |
... | @@ -58,18 +59,13 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -58,18 +59,13 @@ public class DistributedDhcpStore implements DhcpStore { |
58 | protected StorageService storageService; | 59 | protected StorageService storageService; |
59 | 60 | ||
60 | private ConsistentMap<HostId, IpAssignment> allocationMap; | 61 | private ConsistentMap<HostId, IpAssignment> allocationMap; |
61 | - | ||
62 | private DistributedSet<Ip4Address> freeIPPool; | 62 | private DistributedSet<Ip4Address> freeIPPool; |
63 | 63 | ||
64 | private static Ip4Address startIPRange; | 64 | private static Ip4Address startIPRange; |
65 | - | ||
66 | private static Ip4Address endIPRange; | 65 | private static Ip4Address endIPRange; |
67 | 66 | ||
68 | // Hardcoded values are default values. | 67 | // Hardcoded values are default values. |
69 | - | ||
70 | private static int timeoutForPendingAssignments = 60; | 68 | private static int timeoutForPendingAssignments = 60; |
71 | - private static final int MAX_RETRIES = 3; | ||
72 | - private static final int MAX_BACKOFF = 10; | ||
73 | 69 | ||
74 | @Activate | 70 | @Activate |
75 | protected void activate() { | 71 | protected void activate() { |
... | @@ -109,9 +105,9 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -109,9 +105,9 @@ public class DistributedDhcpStore implements DhcpStore { |
109 | IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus(); | 105 | IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus(); |
110 | Ip4Address ipAddr = assignmentInfo.ipAddress(); | 106 | Ip4Address ipAddr = assignmentInfo.ipAddress(); |
111 | 107 | ||
112 | - if (assignmentInfo.rangeNotEnforced()) { | 108 | + if (assignmentInfo.assignmentStatus().equals(Option_RangeNotEnforced)) { |
113 | return assignmentInfo.ipAddress(); | 109 | return assignmentInfo.ipAddress(); |
114 | - } else if (status == IpAssignment.AssignmentStatus.Option_Assigned || | 110 | + } else if (status == Option_Assigned || |
115 | status == IpAssignment.AssignmentStatus.Option_Requested) { | 111 | status == IpAssignment.AssignmentStatus.Option_Requested) { |
116 | // Client has a currently Active Binding. | 112 | // Client has a currently Active Binding. |
117 | if (ipWithinRange(ipAddr)) { | 113 | if (ipWithinRange(ipAddr)) { |
... | @@ -166,82 +162,65 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -166,82 +162,65 @@ public class DistributedDhcpStore implements DhcpStore { |
166 | } | 162 | } |
167 | 163 | ||
168 | @Override | 164 | @Override |
169 | - public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced, | 165 | + public boolean assignIP(HostId hostId, IpAssignment ipAssignment) { |
170 | - List<Ip4Address> addressList) { | 166 | + log.trace("Assign IP Called HostId: {}, ipAssignment: {}", |
171 | - log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString()); | 167 | + hostId, ipAssignment); |
172 | 168 | ||
173 | - Versioned<IpAssignment> currentAssignment = allocationMap.get(hostId); | ||
174 | IpAssignment newAssignment = null; | 169 | IpAssignment newAssignment = null; |
175 | - if (currentAssignment == null) { | 170 | + Versioned<IpAssignment> versionedAssignment = allocationMap.get(hostId); |
176 | - if (rangeNotEnforced) { | 171 | + Ip4Address requestedIp = ipAssignment.ipAddress(); |
177 | - newAssignment = IpAssignment.builder() | 172 | + |
178 | - .ipAddress(ipAddr) | 173 | + if (versionedAssignment == null) { |
179 | - .timestamp(new Date()) | 174 | + // this is new IP assignment of static mapping |
180 | - .leasePeriod(leaseTime) | 175 | + // dynamic assignment is done in suggestIP |
181 | - .rangeNotEnforced(true) | 176 | + if (ipAssignment.assignmentStatus().equals(Option_RangeNotEnforced)) { |
182 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced) | 177 | + newAssignment = ipAssignment; |
183 | - .subnetMask((Ip4Address) addressList.toArray()[0]) | 178 | + } else if (freeIPPool.remove(requestedIp)) { |
184 | - .dhcpServer((Ip4Address) addressList.toArray()[1]) | 179 | + newAssignment = IpAssignment.builder(ipAssignment) |
185 | - .routerAddress((Ip4Address) addressList.toArray()[2]) | 180 | + .assignmentStatus(Option_Assigned) |
186 | - .domainServer((Ip4Address) addressList.toArray()[3]) | ||
187 | - .build(); | ||
188 | - | ||
189 | - } else if (freeIPPool.remove(ipAddr)) { | ||
190 | - newAssignment = IpAssignment.builder() | ||
191 | - .ipAddress(ipAddr) | ||
192 | .timestamp(new Date()) | 181 | .timestamp(new Date()) |
193 | - .leasePeriod(leaseTime) | ||
194 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
195 | .build(); | 182 | .build(); |
196 | } else { | 183 | } else { |
184 | + log.trace("Failed to assign IP for {}", ipAssignment); | ||
197 | return false; | 185 | return false; |
198 | } | 186 | } |
187 | + log.trace("Assigned {}", newAssignment); | ||
199 | return allocationMap.putIfAbsent(hostId, newAssignment) == null; | 188 | return allocationMap.putIfAbsent(hostId, newAssignment) == null; |
200 | // TODO: handle the case where map changed. | 189 | // TODO: handle the case where map changed. |
201 | } else { | 190 | } else { |
202 | - IpAssignment existingAssignment = currentAssignment.value(); | 191 | + // this is lease renew or rebinding |
203 | - if (Objects.equals(existingAssignment.ipAddress(), ipAddr) && | 192 | + // update assignment status and time stamp, and keep the others |
204 | - (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) { | 193 | + IpAssignment existingAssignment = versionedAssignment.value(); |
194 | + if (!existingAssignment.ipAddress().equals(requestedIp)) { | ||
195 | + // return false if existing assignment is not for the | ||
196 | + // requested host | ||
197 | + log.trace("Failed to assign IP for {}", ipAssignment); | ||
198 | + return false; | ||
199 | + } | ||
200 | + | ||
205 | switch (existingAssignment.assignmentStatus()) { | 201 | switch (existingAssignment.assignmentStatus()) { |
206 | case Option_RangeNotEnforced: | 202 | case Option_RangeNotEnforced: |
207 | - newAssignment = IpAssignment.builder() | 203 | + newAssignment = IpAssignment.builder(existingAssignment) |
208 | - .ipAddress(ipAddr) | ||
209 | .timestamp(new Date()) | 204 | .timestamp(new Date()) |
210 | - .leasePeriod(existingAssignment.leasePeriod()) | ||
211 | - .rangeNotEnforced(true) | ||
212 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced) | ||
213 | - .subnetMask(existingAssignment.subnetMask()) | ||
214 | - .dhcpServer(existingAssignment.dhcpServer()) | ||
215 | - .routerAddress(existingAssignment.routerAddress()) | ||
216 | - .domainServer(existingAssignment.domainServer()) | ||
217 | .build(); | 205 | .build(); |
218 | break; | 206 | break; |
207 | + case Option_Expired: | ||
208 | + if (!freeIPPool.remove(requestedIp)) { | ||
209 | + // requested IP is expired for this host and reserved to the other host | ||
210 | + return false; | ||
211 | + } | ||
219 | case Option_Assigned: | 212 | case Option_Assigned: |
220 | case Option_Requested: | 213 | case Option_Requested: |
221 | - newAssignment = IpAssignment.builder() | 214 | + newAssignment = IpAssignment.builder(existingAssignment) |
222 | - .ipAddress(ipAddr) | ||
223 | - .timestamp(new Date()) | ||
224 | - .leasePeriod(leaseTime) | ||
225 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
226 | - .build(); | ||
227 | - break; | ||
228 | - case Option_Expired: | ||
229 | - if (freeIPPool.remove(ipAddr)) { | ||
230 | - newAssignment = IpAssignment.builder() | ||
231 | - .ipAddress(ipAddr) | ||
232 | .timestamp(new Date()) | 215 | .timestamp(new Date()) |
233 | - .leasePeriod(leaseTime) | 216 | + .assignmentStatus(Option_Assigned) |
234 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
235 | .build(); | 217 | .build(); |
236 | - } | ||
237 | break; | 218 | break; |
238 | default: | 219 | default: |
239 | break; | 220 | break; |
240 | } | 221 | } |
241 | - return allocationMap.replace(hostId, currentAssignment.version(), newAssignment); | 222 | + log.trace("Assigned {}", newAssignment); |
242 | - } else { | 223 | + return allocationMap.replace(hostId, versionedAssignment.version(), newAssignment); |
243 | - return false; | ||
244 | - } | ||
245 | } | 224 | } |
246 | } | 225 | } |
247 | 226 | ||
... | @@ -273,8 +252,8 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -273,8 +252,8 @@ public class DistributedDhcpStore implements DhcpStore { |
273 | IpAssignment assignment; | 252 | IpAssignment assignment; |
274 | for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { | 253 | for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { |
275 | assignment = entry.getValue().value(); | 254 | assignment = entry.getValue().value(); |
276 | - if (assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_Assigned | 255 | + if (assignment.assignmentStatus() == Option_Assigned |
277 | - || assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_RangeNotEnforced) { | 256 | + || assignment.assignmentStatus() == Option_RangeNotEnforced) { |
278 | validMapping.put(entry.getKey(), assignment); | 257 | validMapping.put(entry.getKey(), assignment); |
279 | } | 258 | } |
280 | } | 259 | } |
... | @@ -291,10 +270,9 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -291,10 +270,9 @@ public class DistributedDhcpStore implements DhcpStore { |
291 | } | 270 | } |
292 | 271 | ||
293 | @Override | 272 | @Override |
294 | - public boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean rangeNotEnforced, | 273 | + public boolean assignStaticIP(MacAddress macAddress, IpAssignment ipAssignment) { |
295 | - List<Ip4Address> addressList) { | 274 | + HostId host = HostId.hostId(macAddress); |
296 | - HostId host = HostId.hostId(macID); | 275 | + return assignIP(host, ipAssignment); |
297 | - return assignIP(host, ipAddr, -1, rangeNotEnforced, addressList); | ||
298 | } | 276 | } |
299 | 277 | ||
300 | @Override | 278 | @Override |
... | @@ -303,7 +281,7 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -303,7 +281,7 @@ public class DistributedDhcpStore implements DhcpStore { |
303 | if (allocationMap.containsKey(host)) { | 281 | if (allocationMap.containsKey(host)) { |
304 | IpAssignment assignment = allocationMap.get(host).value(); | 282 | IpAssignment assignment = allocationMap.get(host).value(); |
305 | 283 | ||
306 | - if (assignment.rangeNotEnforced()) { | 284 | + if (assignment.assignmentStatus().equals(Option_RangeNotEnforced)) { |
307 | allocationMap.remove(host); | 285 | allocationMap.remove(host); |
308 | return true; | 286 | return true; |
309 | } | 287 | } |
... | @@ -339,11 +317,16 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -339,11 +317,16 @@ public class DistributedDhcpStore implements DhcpStore { |
339 | nextIP = Ip4Address.valueOf(loopCounter); | 317 | nextIP = Ip4Address.valueOf(loopCounter); |
340 | freeIPPool.add(nextIP); | 318 | freeIPPool.add(nextIP); |
341 | } | 319 | } |
320 | + log.debug("Updated free IP pool {}:{} size:{}", startIP, endIP, freeIPPool.size()); | ||
342 | } | 321 | } |
343 | 322 | ||
344 | @Override | 323 | @Override |
345 | public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) { | 324 | public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) { |
325 | + if (allocationMap.get(hostId) != null) { | ||
346 | return allocationMap.get(hostId).value(); | 326 | return allocationMap.get(hostId).value(); |
327 | + } else { | ||
328 | + return null; | ||
329 | + } | ||
347 | } | 330 | } |
348 | 331 | ||
349 | /** | 332 | /** | ... | ... |
... | @@ -18,7 +18,6 @@ package org.onosproject.dhcp.rest; | ... | @@ -18,7 +18,6 @@ package org.onosproject.dhcp.rest; |
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import com.fasterxml.jackson.databind.node.ArrayNode; | 19 | import com.fasterxml.jackson.databind.node.ArrayNode; |
20 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
21 | -import com.google.common.collect.Lists; | ||
22 | import org.onlab.packet.Ip4Address; | 21 | import org.onlab.packet.Ip4Address; |
23 | import org.onlab.packet.MacAddress; | 22 | import org.onlab.packet.MacAddress; |
24 | import org.onosproject.dhcp.DhcpService; | 23 | import org.onosproject.dhcp.DhcpService; |
... | @@ -36,8 +35,11 @@ import javax.ws.rs.core.MediaType; | ... | @@ -36,8 +35,11 @@ import javax.ws.rs.core.MediaType; |
36 | import javax.ws.rs.core.Response; | 35 | import javax.ws.rs.core.Response; |
37 | import java.io.IOException; | 36 | import java.io.IOException; |
38 | import java.io.InputStream; | 37 | import java.io.InputStream; |
38 | +import java.util.Date; | ||
39 | import java.util.Map; | 39 | import java.util.Map; |
40 | 40 | ||
41 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested; | ||
42 | + | ||
41 | /** | 43 | /** |
42 | * Manage DHCP address assignments. | 44 | * Manage DHCP address assignments. |
43 | */ | 45 | */ |
... | @@ -120,10 +122,15 @@ public class DhcpWebResource extends AbstractWebResource { | ... | @@ -120,10 +122,15 @@ public class DhcpWebResource extends AbstractWebResource { |
120 | JsonNode macID = jsonTree.get("mac"); | 122 | JsonNode macID = jsonTree.get("mac"); |
121 | JsonNode ip = jsonTree.get("ip"); | 123 | JsonNode ip = jsonTree.get("ip"); |
122 | if (macID != null && ip != null) { | 124 | if (macID != null && ip != null) { |
125 | + IpAssignment ipAssignment = IpAssignment.builder() | ||
126 | + .ipAddress(Ip4Address.valueOf(ip.asText())) | ||
127 | + .leasePeriod(service.getLeaseTime()) | ||
128 | + .timestamp(new Date()) | ||
129 | + .assignmentStatus(Option_Requested) | ||
130 | + .build(); | ||
123 | 131 | ||
124 | if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()), | 132 | if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()), |
125 | - Ip4Address.valueOf(ip.asText()), | 133 | + ipAssignment)) { |
126 | - false, Lists.newArrayList())) { | ||
127 | throw new IllegalArgumentException("Static Mapping Failed. " + | 134 | throw new IllegalArgumentException("Static Mapping Failed. " + |
128 | "The IP maybe unavailable."); | 135 | "The IP maybe unavailable."); |
129 | } | 136 | } | ... | ... |
... | @@ -28,6 +28,7 @@ import org.onlab.packet.Ip4Address; | ... | @@ -28,6 +28,7 @@ import org.onlab.packet.Ip4Address; |
28 | import org.onlab.packet.IpAddress; | 28 | import org.onlab.packet.IpAddress; |
29 | import org.onlab.packet.MacAddress; | 29 | import org.onlab.packet.MacAddress; |
30 | import org.onlab.packet.UDP; | 30 | import org.onlab.packet.UDP; |
31 | +import org.onosproject.cfg.ComponentConfigAdapter; | ||
31 | import org.onosproject.core.CoreServiceAdapter; | 32 | import org.onosproject.core.CoreServiceAdapter; |
32 | import org.onosproject.dhcp.DhcpStore; | 33 | import org.onosproject.dhcp.DhcpStore; |
33 | import org.onosproject.dhcp.IpAssignment; | 34 | import org.onosproject.dhcp.IpAssignment; |
... | @@ -93,6 +94,7 @@ public class DhcpManagerTest { | ... | @@ -93,6 +94,7 @@ public class DhcpManagerTest { |
93 | hostProviderService = new TestHostProviderService(new TestHostProvider()); | 94 | hostProviderService = new TestHostProviderService(new TestHostProvider()); |
94 | dhcpXManager.hostProviderService = hostProviderService; | 95 | dhcpXManager.hostProviderService = hostProviderService; |
95 | dhcpXManager.hostProviderRegistry = new TestHostRegistry(); | 96 | dhcpXManager.hostProviderRegistry = new TestHostRegistry(); |
97 | + dhcpXManager.componentConfigService = new TestComponentConfig(); | ||
96 | dhcpXManager.activate(); | 98 | dhcpXManager.activate(); |
97 | } | 99 | } |
98 | 100 | ||
... | @@ -228,8 +230,7 @@ public class DhcpManagerTest { | ... | @@ -228,8 +230,7 @@ public class DhcpManagerTest { |
228 | return Ip4Address.valueOf(EXPECTED_IP); | 230 | return Ip4Address.valueOf(EXPECTED_IP); |
229 | } | 231 | } |
230 | 232 | ||
231 | - public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean fromOpenStack, | 233 | + public boolean assignIP(HostId hostId, IpAssignment ipAssignment) { |
232 | - List<Ip4Address> addressList) { | ||
233 | return true; | 234 | return true; |
234 | } | 235 | } |
235 | 236 | ||
... | @@ -256,8 +257,7 @@ public class DhcpManagerTest { | ... | @@ -256,8 +257,7 @@ public class DhcpManagerTest { |
256 | return map; | 257 | return map; |
257 | } | 258 | } |
258 | 259 | ||
259 | - public boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean fromOpenStack, | 260 | + public boolean assignStaticIP(MacAddress macID, IpAssignment ipAssignment) { |
260 | - List<Ip4Address> addressList) { | ||
261 | return true; | 261 | return true; |
262 | } | 262 | } |
263 | 263 | ||
... | @@ -327,6 +327,13 @@ public class DhcpManagerTest { | ... | @@ -327,6 +327,13 @@ public class DhcpManagerTest { |
327 | } | 327 | } |
328 | 328 | ||
329 | /** | 329 | /** |
330 | + * Mocks the ComponentConfigRegistry. | ||
331 | + */ | ||
332 | + private class TestComponentConfig extends ComponentConfigAdapter { | ||
333 | + | ||
334 | + } | ||
335 | + | ||
336 | + /** | ||
330 | * Mocks the HostProviderService. | 337 | * Mocks the HostProviderService. |
331 | */ | 338 | */ |
332 | private class TestHostProviderService extends AbstractProviderService<HostProvider> | 339 | private class TestHostProviderService extends AbstractProviderService<HostProvider> | ... | ... |
... | @@ -9,11 +9,11 @@ | ... | @@ -9,11 +9,11 @@ |
9 | "router": "10.0.0.1", | 9 | "router": "10.0.0.1", |
10 | "domain": "10.0.0.1", | 10 | "domain": "10.0.0.1", |
11 | "ttl": "63", | 11 | "ttl": "63", |
12 | - "lease": "300", | 12 | + "lease": 300, |
13 | "renew": "150", | 13 | "renew": "150", |
14 | - "rebind": "200", | 14 | + "rebind": 200, |
15 | "delay": "3", | 15 | "delay": "3", |
16 | - "timeout": "150", | 16 | + "timeout": 150, |
17 | "startip": "10.0.0.110", | 17 | "startip": "10.0.0.110", |
18 | "endip": "10.0.0.130" | 18 | "endip": "10.0.0.130" |
19 | } | 19 | } | ... | ... |
... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.openstacknetworking.switching; | 16 | package org.onosproject.openstacknetworking.switching; |
17 | 17 | ||
18 | -import com.google.common.collect.ImmutableList; | ||
19 | import com.google.common.collect.ImmutableMap; | 18 | import com.google.common.collect.ImmutableMap; |
20 | import com.google.common.collect.Maps; | 19 | import com.google.common.collect.Maps; |
21 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
... | @@ -26,9 +25,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -26,9 +25,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
27 | import org.onlab.packet.Ethernet; | 26 | import org.onlab.packet.Ethernet; |
28 | import org.onlab.packet.Ip4Address; | 27 | import org.onlab.packet.Ip4Address; |
28 | +import org.onlab.packet.IpPrefix; | ||
29 | import org.onosproject.core.ApplicationId; | 29 | import org.onosproject.core.ApplicationId; |
30 | import org.onosproject.core.CoreService; | 30 | import org.onosproject.core.CoreService; |
31 | import org.onosproject.dhcp.DhcpService; | 31 | import org.onosproject.dhcp.DhcpService; |
32 | +import org.onosproject.dhcp.IpAssignment; | ||
32 | import org.onosproject.event.AbstractEvent; | 33 | import org.onosproject.event.AbstractEvent; |
33 | import org.onosproject.net.Device; | 34 | import org.onosproject.net.Device; |
34 | import org.onosproject.net.DeviceId; | 35 | import org.onosproject.net.DeviceId; |
... | @@ -61,13 +62,18 @@ import org.onosproject.openstacknetworking.OpenstackNetworkingConfig; | ... | @@ -61,13 +62,18 @@ import org.onosproject.openstacknetworking.OpenstackNetworkingConfig; |
61 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; | 62 | import org.onosproject.openstacknetworking.OpenstackSwitchingService; |
62 | import org.slf4j.Logger; | 63 | import org.slf4j.Logger; |
63 | import org.slf4j.LoggerFactory; | 64 | import org.slf4j.LoggerFactory; |
64 | -import java.util.List; | 65 | + |
66 | +import java.util.Date; | ||
65 | import java.util.Collection; | 67 | import java.util.Collection; |
66 | import java.util.Map; | 68 | import java.util.Map; |
67 | import java.util.concurrent.ExecutorService; | 69 | import java.util.concurrent.ExecutorService; |
68 | import java.util.concurrent.Executors; | 70 | import java.util.concurrent.Executors; |
69 | 71 | ||
70 | import static org.onlab.util.Tools.groupedThreads; | 72 | import static org.onlab.util.Tools.groupedThreads; |
73 | +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced; | ||
74 | + | ||
75 | +import static com.google.common.base.Preconditions.checkArgument; | ||
76 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
71 | 77 | ||
72 | @Service | 78 | @Service |
73 | @Component(immediate = true) | 79 | @Component(immediate = true) |
... | @@ -117,8 +123,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -117,8 +123,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
117 | public static final String PORTNAME = "portName"; | 123 | public static final String PORTNAME = "portName"; |
118 | private static final String ROUTER_INTERFACE = "network:router_interface"; | 124 | private static final String ROUTER_INTERFACE = "network:router_interface"; |
119 | public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway"; | 125 | public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway"; |
120 | - public static final String DNS_SERVER_IP = "8.8.8.8"; | 126 | + public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8"); |
121 | private static final String FORWARD_SLASH = "/"; | 127 | private static final String FORWARD_SLASH = "/"; |
128 | + private static final int DHCP_INFINITE_LEASE = -1; | ||
122 | 129 | ||
123 | 130 | ||
124 | private ApplicationId appId; | 131 | private ApplicationId appId; |
... | @@ -372,42 +379,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -372,42 +379,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
372 | } | 379 | } |
373 | 380 | ||
374 | private void registerDhcpInfo(OpenstackPort openstackPort) { | 381 | private void registerDhcpInfo(OpenstackPort openstackPort) { |
375 | - Ip4Address ip4Address, subnetMask, gatewayIPAddress, dhcpServer, domainServer; | 382 | + checkNotNull(openstackPort); |
376 | - OpenstackSubnet openstackSubnet; | 383 | + checkArgument(!openstackPort.fixedIps().isEmpty()); |
377 | 384 | ||
378 | - ip4Address = (Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null); | 385 | + OpenstackSubnet openstackSubnet = openstackService.subnets().stream() |
379 | - | ||
380 | - openstackSubnet = openstackService.subnets().stream() | ||
381 | .filter(n -> n.networkId().equals(openstackPort.networkId())) | 386 | .filter(n -> n.networkId().equals(openstackPort.networkId())) |
382 | - .findFirst().get(); | 387 | + .findFirst().orElse(null); |
383 | - | 388 | + if (openstackSubnet == null) { |
384 | - subnetMask = Ip4Address.valueOf(buildSubnetMask(openstackSubnet.cidr())); | 389 | + log.warn("Failed to find subnet for {}", openstackPort); |
385 | - gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp()); | 390 | + return; |
386 | - dhcpServer = gatewayIPAddress; | ||
387 | - // TODO: supports multiple DNS servers | ||
388 | - if (openstackSubnet.dnsNameservers().isEmpty()) { | ||
389 | - domainServer = Ip4Address.valueOf(DNS_SERVER_IP); | ||
390 | - } else { | ||
391 | - domainServer = openstackSubnet.dnsNameservers().get(0); | ||
392 | - } | ||
393 | - List<Ip4Address> options = ImmutableList.of(subnetMask, dhcpServer, gatewayIPAddress, domainServer); | ||
394 | - | ||
395 | - dhcpService.setStaticMapping(openstackPort.macAddress(), ip4Address, true, options); | ||
396 | } | 391 | } |
397 | 392 | ||
398 | - private byte[] buildSubnetMask(String cidr) { | 393 | + Ip4Address ipAddress = openstackPort.fixedIps().values().stream().findFirst().get(); |
399 | - int prefix; | 394 | + IpPrefix subnetPrefix = IpPrefix.valueOf(openstackSubnet.cidr()); |
400 | - String[] parts = cidr.split(FORWARD_SLASH); | 395 | + Ip4Address broadcast = Ip4Address.makeMaskedAddress( |
401 | - prefix = Integer.parseInt(parts[1]); | 396 | + ipAddress, |
402 | - int mask = 0xffffffff << (32 - prefix); | 397 | + subnetPrefix.prefixLength()); |
403 | - byte[] bytes = new byte[]{(byte) (mask >>> 24), | ||
404 | - (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)}; | ||
405 | 398 | ||
406 | - return bytes; | 399 | + // TODO: supports multiple DNS servers |
400 | + Ip4Address domainServer = openstackSubnet.dnsNameservers().isEmpty() ? | ||
401 | + DNS_SERVER_IP : openstackSubnet.dnsNameservers().get(0); | ||
402 | + | ||
403 | + IpAssignment ipAssignment = IpAssignment.builder() | ||
404 | + .ipAddress(ipAddress) | ||
405 | + .leasePeriod(DHCP_INFINITE_LEASE) | ||
406 | + .timestamp(new Date()) | ||
407 | + .subnetMask(Ip4Address.makeMaskPrefix(subnetPrefix.prefixLength())) | ||
408 | + .broadcast(broadcast) | ||
409 | + .domainServer(domainServer) | ||
410 | + .assignmentStatus(Option_RangeNotEnforced) | ||
411 | + .routerAddress(Ip4Address.valueOf(openstackSubnet.gatewayIp())) | ||
412 | + .build(); | ||
413 | + | ||
414 | + dhcpService.setStaticMapping(openstackPort.macAddress(), ipAssignment); | ||
407 | } | 415 | } |
408 | 416 | ||
409 | - | ||
410 | - | ||
411 | private class InternalPacketProcessor implements PacketProcessor { | 417 | private class InternalPacketProcessor implements PacketProcessor { |
412 | 418 | ||
413 | @Override | 419 | @Override | ... | ... |
-
Please register or login to post a comment