Hyunsun Moon
Committed by Gerrit Code Review

CORD-484 Support management network for a VM

Change-Id: I866ae3ae7d839cd29f1732605170f3dfbab402bb
...@@ -38,7 +38,8 @@ public final class CordService { ...@@ -38,7 +38,8 @@ public final class CordService {
38 PRIVATE_DIRECT, 38 PRIVATE_DIRECT,
39 PRIVATE_INDIRECT, 39 PRIVATE_INDIRECT,
40 PUBLIC_DIRECT, 40 PUBLIC_DIRECT,
41 - PUBLIC_INDIRECT 41 + PUBLIC_INDIRECT,
42 + MANAGEMENT
42 } 43 }
43 44
44 private final CordServiceId id; 45 private final CordServiceId id;
...@@ -165,7 +166,7 @@ public final class CordService { ...@@ -165,7 +166,7 @@ public final class CordService {
165 * It assumes that network name contains network type. 166 * It assumes that network name contains network type.
166 * 167 *
167 * @param netName network name 168 * @param netName network name
168 - * @return network type, or null if it doesn't match any type 169 + * @return network type, or PRIVATE if it doesn't match any type
169 */ 170 */
170 private ServiceType getServiceType(String netName) { 171 private ServiceType getServiceType(String netName) {
171 checkNotNull(netName); 172 checkNotNull(netName);
...@@ -179,10 +180,10 @@ public final class CordService { ...@@ -179,10 +180,10 @@ public final class CordService {
179 return PUBLIC_DIRECT; 180 return PUBLIC_DIRECT;
180 } else if (name.contains(PUBLIC_INDIRECT.toString())) { 181 } else if (name.contains(PUBLIC_INDIRECT.toString())) {
181 return PUBLIC_INDIRECT; 182 return PUBLIC_INDIRECT;
182 - } else if (name.contains(PRIVATE.toString())) { 183 + } else if (name.contains(MANAGEMENT.toString())) {
183 - return PRIVATE; 184 + return MANAGEMENT;
184 } else { 185 } else {
185 - return null; 186 + return PRIVATE;
186 } 187 }
187 } 188 }
188 } 189 }
......
...@@ -403,7 +403,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -403,7 +403,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
403 host.ipAddresses().stream().findFirst().get()); 403 host.ipAddresses().stream().findFirst().get());
404 404
405 CordService service = getCordService(vNet); 405 CordService service = getCordService(vNet);
406 - if (service != null) { 406 + if (service == null) {
407 + return;
408 + }
409 +
410 + if (service.serviceType().equals(CordService.ServiceType.MANAGEMENT)) {
411 + ruleInstaller.populateManagementNetworkRules(host, service);
412 + } else {
407 // TODO check if the service needs an update on its group buckets after done CORD-433 413 // TODO check if the service needs an update on its group buckets after done CORD-433
408 ruleInstaller.updateServiceGroup(service); 414 ruleInstaller.updateServiceGroup(service);
409 arpProxy.addServiceIp(service.serviceIp()); 415 arpProxy.addServiceIp(service.serviceIp());
...@@ -440,7 +446,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro ...@@ -440,7 +446,13 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro
440 ruleInstaller.removeBasicConnectionRules(host); 446 ruleInstaller.removeBasicConnectionRules(host);
441 447
442 CordService service = getCordService(vNet); 448 CordService service = getCordService(vNet);
443 - if (service != null) { 449 + if (service == null) {
450 + return;
451 + }
452 +
453 + if (service.serviceType().equals(CordService.ServiceType.MANAGEMENT)) {
454 + ruleInstaller.removeManagementNetworkRules(host, service);
455 + } else {
444 // TODO check if the service needs an update on its group buckets after done CORD-433 456 // TODO check if the service needs an update on its group buckets after done CORD-433
445 ruleInstaller.updateServiceGroup(service); 457 ruleInstaller.updateServiceGroup(service);
446 458
......
...@@ -103,10 +103,11 @@ public class CordVtnRuleInstaller { ...@@ -103,10 +103,11 @@ public class CordVtnRuleInstaller {
103 private static final int TABLE_DST_IP = 4; 103 private static final int TABLE_DST_IP = 4;
104 private static final int TABLE_TUNNEL_IN = 5; 104 private static final int TABLE_TUNNEL_IN = 5;
105 105
106 + private static final int MANAGEMENT_PRIORITY = 55000;
107 + private static final int HIGH_PRIORITY = 50000;
106 private static final int DEFAULT_PRIORITY = 5000; 108 private static final int DEFAULT_PRIORITY = 5000;
107 - private static final int LOWER_PRIORITY = 4000; 109 + private static final int LOW_PRIORITY = 4000;
108 private static final int LOWEST_PRIORITY = 0; 110 private static final int LOWEST_PRIORITY = 0;
109 - private static final int HIGHER_PRIORITY = 50000;
110 111
111 private static final int VXLAN_UDP_PORT = 4789; 112 private static final int VXLAN_UDP_PORT = 4789;
112 113
...@@ -387,6 +388,126 @@ public class CordVtnRuleInstaller { ...@@ -387,6 +388,126 @@ public class CordVtnRuleInstaller {
387 } 388 }
388 389
389 /** 390 /**
391 + * Populates flow rules for management network access.
392 + *
393 + * @param host host which has management network interface
394 + * @param mService management network service
395 + */
396 + public void populateManagementNetworkRules(Host host, CordService mService) {
397 + checkNotNull(mService);
398 +
399 + DeviceId deviceId = host.location().deviceId();
400 + IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
401 +
402 + TrafficSelector selector = DefaultTrafficSelector.builder()
403 + .matchEthType(Ethernet.TYPE_ARP)
404 + .matchArpTpa(mService.serviceIp().getIp4Address())
405 + .build();
406 +
407 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
408 + .setOutput(PortNumber.LOCAL)
409 + .build();
410 +
411 + FlowRule flowRule = DefaultFlowRule.builder()
412 + .fromApp(appId)
413 + .withSelector(selector)
414 + .withTreatment(treatment)
415 + .withPriority(MANAGEMENT_PRIORITY)
416 + .forDevice(deviceId)
417 + .forTable(TABLE_FIRST)
418 + .makePermanent()
419 + .build();
420 +
421 + processFlowRule(true, flowRule);
422 +
423 + selector = DefaultTrafficSelector.builder()
424 + .matchInPort(PortNumber.LOCAL)
425 + .matchEthType(Ethernet.TYPE_ARP)
426 + .matchArpTpa(hostIp.getIp4Address())
427 + .build();
428 +
429 + treatment = DefaultTrafficTreatment.builder()
430 + .setOutput(host.location().port())
431 + .build();
432 +
433 + flowRule = DefaultFlowRule.builder()
434 + .fromApp(appId)
435 + .withSelector(selector)
436 + .withTreatment(treatment)
437 + .withPriority(MANAGEMENT_PRIORITY)
438 + .forDevice(deviceId)
439 + .forTable(TABLE_FIRST)
440 + .makePermanent()
441 + .build();
442 +
443 + processFlowRule(true, flowRule);
444 +
445 + selector = DefaultTrafficSelector.builder()
446 + .matchInPort(PortNumber.LOCAL)
447 + .matchEthType(Ethernet.TYPE_IPV4)
448 + .matchIPDst(mService.serviceIpRange())
449 + .build();
450 +
451 + treatment = DefaultTrafficTreatment.builder()
452 + .transition(TABLE_DST_IP)
453 + .build();
454 +
455 + flowRule = DefaultFlowRule.builder()
456 + .fromApp(appId)
457 + .withSelector(selector)
458 + .withTreatment(treatment)
459 + .withPriority(MANAGEMENT_PRIORITY)
460 + .forDevice(deviceId)
461 + .forTable(TABLE_FIRST)
462 + .makePermanent()
463 + .build();
464 +
465 + processFlowRule(true, flowRule);
466 +
467 + selector = DefaultTrafficSelector.builder()
468 + .matchEthType(Ethernet.TYPE_IPV4)
469 + .matchIPDst(mService.serviceIp().toIpPrefix())
470 + .build();
471 +
472 + treatment = DefaultTrafficTreatment.builder()
473 + .setOutput(PortNumber.LOCAL)
474 + .build();
475 +
476 + flowRule = DefaultFlowRule.builder()
477 + .fromApp(appId)
478 + .withSelector(selector)
479 + .withTreatment(treatment)
480 + .withPriority(MANAGEMENT_PRIORITY)
481 + .forDevice(deviceId)
482 + .forTable(TABLE_ACCESS_TYPE)
483 + .makePermanent()
484 + .build();
485 +
486 + processFlowRule(true, flowRule);
487 + }
488 +
489 + /**
490 + * Removes management network access rules.
491 + *
492 + * @param host host to be removed
493 + * @param mService service for management network
494 + */
495 + public void removeManagementNetworkRules(Host host, CordService mService) {
496 + checkNotNull(mService);
497 +
498 + for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
499 + if (flowRule.deviceId().equals(host.location().deviceId())) {
500 + PortNumber port = getOutputFromTreatment(flowRule);
501 + if (port != null && port.equals(host.location().port())) {
502 + processFlowRule(false, flowRule);
503 + }
504 + }
505 +
506 + // TODO remove the other rules if mgmt network is not in use
507 + }
508 + }
509 +
510 + /**
390 * Populates default rules on the first table. 511 * Populates default rules on the first table.
391 * The rules are for shuttling vxlan-encapped packets and supporting physical 512 * The rules are for shuttling vxlan-encapped packets and supporting physical
392 * network connectivity. 513 * network connectivity.
...@@ -409,7 +530,7 @@ public class CordVtnRuleInstaller { ...@@ -409,7 +530,7 @@ public class CordVtnRuleInstaller {
409 .fromApp(appId) 530 .fromApp(appId)
410 .withSelector(selector) 531 .withSelector(selector)
411 .withTreatment(treatment) 532 .withTreatment(treatment)
412 - .withPriority(HIGHER_PRIORITY) 533 + .withPriority(HIGH_PRIORITY)
413 .forDevice(deviceId) 534 .forDevice(deviceId)
414 .forTable(TABLE_FIRST) 535 .forTable(TABLE_FIRST)
415 .makePermanent() 536 .makePermanent()
...@@ -433,7 +554,7 @@ public class CordVtnRuleInstaller { ...@@ -433,7 +554,7 @@ public class CordVtnRuleInstaller {
433 .fromApp(appId) 554 .fromApp(appId)
434 .withSelector(selector) 555 .withSelector(selector)
435 .withTreatment(treatment) 556 .withTreatment(treatment)
436 - .withPriority(HIGHER_PRIORITY) 557 + .withPriority(HIGH_PRIORITY)
437 .forDevice(deviceId) 558 .forDevice(deviceId)
438 .forTable(TABLE_FIRST) 559 .forTable(TABLE_FIRST)
439 .makePermanent() 560 .makePermanent()
...@@ -456,7 +577,7 @@ public class CordVtnRuleInstaller { ...@@ -456,7 +577,7 @@ public class CordVtnRuleInstaller {
456 .fromApp(appId) 577 .fromApp(appId)
457 .withSelector(selector) 578 .withSelector(selector)
458 .withTreatment(treatment) 579 .withTreatment(treatment)
459 - .withPriority(HIGHER_PRIORITY) 580 + .withPriority(HIGH_PRIORITY)
460 .forDevice(deviceId) 581 .forDevice(deviceId)
461 .forTable(TABLE_FIRST) 582 .forTable(TABLE_FIRST)
462 .makePermanent() 583 .makePermanent()
...@@ -479,7 +600,7 @@ public class CordVtnRuleInstaller { ...@@ -479,7 +600,7 @@ public class CordVtnRuleInstaller {
479 .fromApp(appId) 600 .fromApp(appId)
480 .withSelector(selector) 601 .withSelector(selector)
481 .withTreatment(treatment) 602 .withTreatment(treatment)
482 - .withPriority(HIGHER_PRIORITY) 603 + .withPriority(HIGH_PRIORITY)
483 .forDevice(deviceId) 604 .forDevice(deviceId)
484 .forTable(TABLE_FIRST) 605 .forTable(TABLE_FIRST)
485 .makePermanent() 606 .makePermanent()
...@@ -633,7 +754,7 @@ public class CordVtnRuleInstaller { ...@@ -633,7 +754,7 @@ public class CordVtnRuleInstaller {
633 .fromApp(appId) 754 .fromApp(appId)
634 .withSelector(selector) 755 .withSelector(selector)
635 .withTreatment(treatment) 756 .withTreatment(treatment)
636 - .withPriority(LOWER_PRIORITY) 757 + .withPriority(LOW_PRIORITY)
637 .forDevice(deviceId) 758 .forDevice(deviceId)
638 .forTable(TABLE_IN_PORT) 759 .forTable(TABLE_IN_PORT)
639 .makePermanent() 760 .makePermanent()
...@@ -665,7 +786,7 @@ public class CordVtnRuleInstaller { ...@@ -665,7 +786,7 @@ public class CordVtnRuleInstaller {
665 .fromApp(appId) 786 .fromApp(appId)
666 .withSelector(selector) 787 .withSelector(selector)
667 .withTreatment(treatment) 788 .withTreatment(treatment)
668 - .withPriority(LOWER_PRIORITY) 789 + .withPriority(LOW_PRIORITY)
669 .forDevice(device.id()) 790 .forDevice(device.id())
670 .forTable(TABLE_ACCESS_TYPE) 791 .forTable(TABLE_ACCESS_TYPE)
671 .makePermanent() 792 .makePermanent()
...@@ -1006,6 +1127,25 @@ public class CordVtnRuleInstaller { ...@@ -1006,6 +1127,25 @@ public class CordVtnRuleInstaller {
1006 } 1127 }
1007 1128
1008 /** 1129 /**
1130 + * Returns the output port number from a given flow rule.
1131 + *
1132 + * @param flowRule flow rule
1133 + * @return port number, or null if the rule does not have output instruction
1134 + */
1135 + private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1136 + Instruction instruction = flowRule.treatment().allInstructions().stream()
1137 + .filter(inst -> inst instanceof Instructions.OutputInstruction)
1138 + .findFirst()
1139 + .orElse(null);
1140 +
1141 + if (instruction == null) {
1142 + return null;
1143 + }
1144 +
1145 + return ((Instructions.OutputInstruction) instruction).port();
1146 + }
1147 +
1148 + /**
1009 * Creates a new group for a given service. 1149 * Creates a new group for a given service.
1010 * 1150 *
1011 * @param deviceId device id to create a group 1151 * @param deviceId device id to create a group
......